存储库 +工作单元当详细记录发生更改时,EF 更新主记录。 (总金额=总和(金额))

发布于 2024-10-21 08:49:56 字数 3017 浏览 2 评论 0原文

我正在尝试使用实体框架实现存储库和工作单元模式。

这是这样的场景:

用户可以在主从窗口中添加或修改详细记录,当点击“保存”时,添加/修改的记录将发送到服务器。

然后我执行 CreateOrUpdateMultiple()。 CreateMultiple 将新记录添加到存储库。 UpdateMultiple 检索将要更新的记录。

两个操作完成后,我需要使用包含所有详细记录的总和(字段)更新主记录。 (我的意思是未修改的现有记录和内存中的记录)

这就是我到目前为止的想法...

  1. 作为存储库模式的纯粹主义者,我应该检索所有详细记录,然后应该混合在一个列表中现有记录(修改或未修改)和添加的记录,然后进行求和操作,但是如果详细记录的金额字段是数据库计算字段怎么办?

  2. 仅从数据库中读取要更新的记录(认为这会更快,因为如果我有 40 条记录,只有 3 条被修改,2 条被添加,我将不会读取整个集合),然后以某种方式执行对主记录的更新,但问题是这些记录尚未在数据库中。

我只有一个 ObjectContext 实例用于所有操作,并且我在服务中调用 SaveChanges() 以在一个事务中提交所有操作。

你建议我做什么?或者你如何实现这种情况?

预先感谢

//更新

这里更技术性地描述

这就是我现在使用 transactionScope 所拥有的...这是我试图避免的,因为所有对数据库的调用

//Service Layer
Method()
{
   Method1.Invoke(masterRecordId, detaildRecords); //
}

//Business Layer
Method1(masterRecordId, detailRecords)
{
     using(TransactionScope ts = new TransactionScope())
     {
          var recordsToUpdate = dal.RetrieveOnlyRecordsToUpdate();

          //Update retrieved records with the values of recods comming from the client
          dal.Update(recordsToUpdate); //ctx.ApplyChanges(); and ctx.SaveChanges();

          dal.Add(recordsToAdd) //ctx.Add(detail records); and ctx.SaveChanges();

          //Update master record TotalSum
          dal.UpdateMasterRecord(masterRecordId); //Here is performed ctx.ExecuteStoredCommand("UPDATE MasterTable = SUM() WHERE MasterRecordId = {0}")...

          Method2();

          ts.Complete();
     }
}

Method2(masterRecordId)
{
     using(TransactionScope ts = new TransactionScope())
     {
          MasterRecord m = Retrieve(masteRecordId);
          Notification notification = new Notification(){ ...assign properties..., m.TotalSum};

          dal.Add(notification); //ctx.Add(notification); and ctx.SaveChanges();

          ts.Complete(); 
     }
}

这就是我想要做的...

//Service Layer
Method()
{
  Method1.Invoke(masterRecordId, detail records);

  UnitOfWorkManager.Current.Commit(); //
}

//Business Layer
Metodo1(masterRecordId, detail records)
{
          MasterRecord masterRecord = repository.Retrieve(masterRecordId);

          var recordsToUpdate = repository.RetrieveOnlyRecordsToUpdate();

          //Update retrieved records with the values of recods comming from the client
          repository.Modify(recordsToUpdate); 

          repository.Add(recordsToAdd); 

          //Here i'm stuck and i'm thinking it should be something like this.
          masterRecord.TotalSum = sum(detailRecords in memory + detail records in database); //
          repository.Modify(masterRecord); //

          or

          //Another way somehow...

          //Then keep going with the udpated master record
          Method2(masterRecord);
     }
}

Method2(masterRecord)
{
     //Create notification
     var notification = new Notification(){ ...properties.., masterRecord.TotalSum};
     repository.Add(notification);
}

i'm trying to implement a Repository and UnitOfWork patterns using Entity Framework.

This is the scenario:

An user can add or modify detail records in a master-detail window and when hit "save" the added/modified records are sent to the server.

Then i perform a CreateOrUpdateMultiple().
CreateMultiple add the new records to the repository.
UpdateMultiple retrieve records that going to be updated.

After the two operations completes i need to update the master record with a sum(field) with all detail records. (With all i mean the existing ones that were not modified and the ones in memory)

This is what i have thought so far...

  1. Being purist with repository pattern i should retrieve all detail records and then should mix in one list the existing records (modified or not) and the addded ones, and then do the sum operation, but what if the amount field of detail records is a database calculated field?

  2. Read from database only records to be updated (thinking this will be faster because if i have 40 records and just 3 are modified and 2 added i will not read the entire set) and then somehow perform the update to the master record, but the problem is those records aren't yet in the database.

I have just one ObjectContext instance for all operations and i call SaveChanges() in my service to commit all in just one transaction.

What do you advice me to do? Or how do you archieve this kind of situation?

Thanks in advance

//Update

Here more technically described

The is what i have right now using transactionScope... and this is what i'm trying to avoid because of all the calls to database

//Service Layer
Method()
{
   Method1.Invoke(masterRecordId, detaildRecords); //
}

//Business Layer
Method1(masterRecordId, detailRecords)
{
     using(TransactionScope ts = new TransactionScope())
     {
          var recordsToUpdate = dal.RetrieveOnlyRecordsToUpdate();

          //Update retrieved records with the values of recods comming from the client
          dal.Update(recordsToUpdate); //ctx.ApplyChanges(); and ctx.SaveChanges();

          dal.Add(recordsToAdd) //ctx.Add(detail records); and ctx.SaveChanges();

          //Update master record TotalSum
          dal.UpdateMasterRecord(masterRecordId); //Here is performed ctx.ExecuteStoredCommand("UPDATE MasterTable = SUM() WHERE MasterRecordId = {0}")...

          Method2();

          ts.Complete();
     }
}

Method2(masterRecordId)
{
     using(TransactionScope ts = new TransactionScope())
     {
          MasterRecord m = Retrieve(masteRecordId);
          Notification notification = new Notification(){ ...assign properties..., m.TotalSum};

          dal.Add(notification); //ctx.Add(notification); and ctx.SaveChanges();

          ts.Complete(); 
     }
}

This is what i want to do...

//Service Layer
Method()
{
  Method1.Invoke(masterRecordId, detail records);

  UnitOfWorkManager.Current.Commit(); //
}

//Business Layer
Metodo1(masterRecordId, detail records)
{
          MasterRecord masterRecord = repository.Retrieve(masterRecordId);

          var recordsToUpdate = repository.RetrieveOnlyRecordsToUpdate();

          //Update retrieved records with the values of recods comming from the client
          repository.Modify(recordsToUpdate); 

          repository.Add(recordsToAdd); 

          //Here i'm stuck and i'm thinking it should be something like this.
          masterRecord.TotalSum = sum(detailRecords in memory + detail records in database); //
          repository.Modify(masterRecord); //

          or

          //Another way somehow...

          //Then keep going with the udpated master record
          Method2(masterRecord);
     }
}

Method2(masterRecord)
{
     //Create notification
     var notification = new Notification(){ ...properties.., masterRecord.TotalSum};
     repository.Add(notification);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枯寂 2024-10-28 08:49:56

如果您想将其作为事务执行,并且仅调用 SaveChanges 一次,则必须在调用 SaveChanges 之前在应用程序中执行此操作。因此,通常在进行任何更改之前必须获取总和,并通过更新值、插入值和删除值修改总和。然后您将新的总和值设置到主记录中。如果你这样做,你就会有工作单元。

为什么其他方法不太好。

  • 数据库中的计算字段。这将需要在保存操作后手动重新加载主实体,因为保存详细信息无法重新加载其他实体中的更改。此外,数据库逻辑可能需要在详细表上触发来修改主表中的总和。
  • 保存对详细信息的更改后更新主记录会破坏工作单元。

If you want to do it as transaction and call SaveChanges only once you must do it in your application before SaveChanges is called. So generally you must get sum before you do any change and modify the sum by updated values, inserted values and deleted values. Then you will set the new sum value into the master record. If you do it this way you will have unit of work.

Why other approaches are not so good.

  • Calculated field in database. This will require manually reloading master entity after the save operation because saving detail cannot reload changes in other entity. Moreover database logic will probably require trigger on detail table to modify sum in master table.
  • Updating master record after saving changes to details breaks unit of work.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文