Linq/Entities:Everything or Nothing(在数据库中)

TGI*_*TGI 4 linq asp.net entity-framework

我试图实现一种只有在没有错误发生时才将数据(实体对象)放入数据库的方法('所有').如果发生错误,则不会在数据库中创建任何内容("或什么都没有").我称之为"一切或全无".

问题是我必须创建依赖于其他实体的实体.这是一个例子:

0)我创建了一个上下文

DBContext ctx = new DBContext();
Run Code Online (Sandbox Code Playgroud)

1)我创建一个Invoice实体对象并将其添加到上下文中:

Invoice inv1 = new Invoice();
inv1 .Number = "Invoice-2546432";

if(!ctx.Invoice.Exists(i => i.Number == "Invoice-2546432")) // problem n°1
   ctx.AddObject(inv1 );
else 
   throws new Exception('blah blah');
Run Code Online (Sandbox Code Playgroud)

2)发票上有发票行:

InvoiceLine line = new InvoiceLine();
line .ID_INVOICE = in1.ID; // problem n°2
line .Label = "Line 1";
line .Ammount = 5.3;
ctx.AddObject(line );
Run Code Online (Sandbox Code Playgroud)

3)最后:

ctx.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

所以,如果一切顺利,我会有这样的事情:

   Table INVOICE
=====================
ID  |      NUMBER
_____________________
 0  |  Invoice-2454876
_____________________
 1  |  Invoice-2487432
_____________________
 2  |  Invoice-2546432


           Table INVOICE_LINE
=========================================
ID  |  ID_INVOICE  |   LABEL   |  AMOUNT 
_________________________________________
 0  |       0      |   Line 1  |   2.6    
_________________________________________
 1  |       0      |   Line 2  |   7.6    
_________________________________________
 2  |       1      |   Line 1  |   7.6    
_________________________________________
 3  |       2      |   Line 1  |   8.6    
_________________________________________
Run Code Online (Sandbox Code Playgroud)

正如评论中所提到的,有两个问题:

问题1:

存在测试总是返回false,因为它只检查数据库而不是我刚添加新对象的上下文本身.

问题2:

由于发票仅添加到上下文而不是数据库中,因此我没有发票的未来ID.所以我无法将其设置为发票行.

1)你知道如何做到这一点,基本上是一种将数据添加到数据库的安全方法吗?我正在开发一个财务应用程序,我想确保没有损坏的数据插入数据库(例如:如果插入发票行失败,我希望整个发票不插入数据库)

2)我没有找到任何与此类事物相关的设计模式.你知道吗,有机会吗?

3)我不确定在实体框架中有很好理解的上下文对象:这是我的理解:

上下文(基本上)是与数据库的连接.当我添加一个实体时,它会被保存在内存中的某个位置并在我调用SaveChanges()后插入到数据库中.它是否正确 ?您是否知道任何网站或书籍详细介绍了ADO /实体框架的工作原理?

Stu*_*tLC 6

看起来你仍然在思考sqlrecord思维方式--EF是一个ORM并且完成了你所描述的大部分低级内务管理.

理想情况下,由于似乎很明显,在Invoice和之间存在1:多关系InvoiceLine,您应该在EF中建立这种1:N关系,然后让EF担心修复/分配标识列,即:

Invoice invoice = new Invoice();
invoice.InvoiceLines.Add(new InvoiceLine() { ... set fields here })
... add more details

// Now add just the invoice to the context. The lines will be added automatically
ctx.AddObject(invoice);
ctx.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

要回答第二个问题,您可以考虑使用TransactionScope()在单个工作单元下聚合多个数据库操作.

回答你的上一个问题 - 你不应该将上下文视为数据库连接 - 它是一个更高层次的概念,它管理由它管理的实体的状态.

另请注意,SaveChanges()本身应确保对上下文的所有更改都将在事务下保留,因此如果使用单个上下文,通常不需要其他事务控制.

这些所谓的帖子在这里这里应该帮助?