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

时间:2013-01-04 10:17:50

标签: asp.net linq entity-framework

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

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

0)我创建了一个上下文

DBContext ctx = new DBContext();

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');

2)发票上有发票行:

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

3)最后:

ctx.SaveChanges();

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

   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    
_________________________________________

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

问题n°1:

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

问题n°2:

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

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

2)我没有找到任何与此类事物相关的设计模式。你知道一个吗?

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

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

2 个答案:

答案 0 :(得分:6)

您似乎仍在考虑sqlrecord心态--EF是一个ORM并且执行了您所描述的大部分低级管家。

理想情况下,由于似乎InvoiceInvoiceLine之间存在1:多关系,因此您应该在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();

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

回答您的上一个问题 - 您不应将上下文视为数据库连接 - 它是一个更高级别的概念,用于管理由其管理的实体的状态。

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

这些SO帖子herehere应该有帮助吗?

答案 1 :(得分:-1)

要回答您的第二个问题,您可以在发票表中添加额外字段,例如状态为位。如果保存所有发票行而没有任何异常,则最后更新相关发票并设置Status = true。

使用TransactionScope

使逻辑变得非常复杂。 transactioncope不够智能,无法解决所有问题。