4

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

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

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    
_________________________________________

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

问题 1:

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

问题二:

因为发票只是添加到上下文中而不是在数据库中,所以我没有发票的未来 ID。所以我不能将它设置到发票行。

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

2)我没有找到任何与那种东西相关的设计模式。你认识一个吗?

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

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

4

2 回答 2

6

似乎您仍在思考一种sqlrecord心态 - EF 是一个 ORM,并且执行您所描述的大部分低级内务处理。

Invoice理想情况下,由于和之间存在 1:many 关系似乎很明显,因此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();

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

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

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

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

于 2013-01-04T10:24:42.967 回答
-1

要回答您的 sec 问题,您可以在发票表中添加一个额外字段,例如 Status as bit。如果您最终保存了所有发票行,没有任何例外,您将更新相关发票并设置 Status = true。

使用 TransactionScope 使逻辑非常复杂。transactionscope 不够聪明,无法弄清楚所有事情。

于 2013-01-04T10:44:00.893 回答