优化存储库的SubmitChanges方法

我有以下存储库。 我使用工厂在LINQ 2 SQL生成的类和域对象之间进行映射。

以下代码将起作用; 但我看到两个潜在的问题

1)它在更新语句之前使用SELECT查询。

2)它需要更新所有列(不仅是更改的列)。 这是因为我们不知道域对象中所有列的更改。

如何克服这些缺点?

注意:可能存在基于特定列更新执行的方案(如触发器)。 所以我不能不必要地更新列。

参考

  1. LINQ to SQL:“UpdateCheck = Never”时不刷新更新

  2. http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=113917

namespace RepositoryLayer { public interface ILijosBankRepository { void SubmitChangesForEntity(); } public class LijosSimpleBankRepository : ILijosBankRepository { private IBankAccountFactory bankFactory = new MySimpleBankAccountFactory(); public System.Data.Linq.DataContext Context { get; set; } public virtual void SubmitChangesForEntity(DomainEntitiesForBank.IBankAccount iBankAcc) { //Does not get help from automated change tracking (due to mapping) //Selecting the required entity DBML_Project.BankAccount tableEntity = Context.GetTable().SingleOrDefault(p => p.BankAccountID == iBankAcc.BankAccountID); if (tableEntity != null) { //Setting all the values to updates (except primary key) tableEntity.Status = iBankAcc.AccountStatus; //Type Checking if (iBankAcc is DomainEntitiesForBank.FixedBankAccount) { tableEntity.AccountType = "Fixed"; } if (iBankAcc is DomainEntitiesForBank.SavingsBankAccount) { tableEntity.AccountType = "Savings"; } Context.SubmitChanges(); } } } } namespace DomainEntitiesForBank { public interface IBankAccount { int BankAccountID { get; set; } double Balance { get; set; } string AccountStatus { get; set; } void FreezeAccount(); } public class FixedBankAccount : IBankAccount { public int BankAccountID { get; set; } public string AccountStatus { get; set; } public double Balance { get; set; } public void FreezeAccount() { AccountStatus = "Frozen"; } } } 

如果我理解了您的问题,那么您将被传递到需要保存到数据库的实体,而不知道原始值是什么,或者哪些列实际已更改。

如果是这种情况,那么您有四种选择

  1. 您需要返回数据库以查看原始值,即执行select,就像您编写的那样。 这允许您设置所有实体值,Linq2Sql将负责实际更改哪些列。 因此,如果没有实际更改任何列,则不会触发任何更新语句。

  2. 您需要避免选择并只更新列。 你已经知道该怎么做了(但对于其他人看到这个问题和答案 )。 由于您不知道哪些列已更改,因此您无法选择所有列。 即使没有实际更改任何列,这也会产生更新语句,这可以触发任何数据库触发器。 除了禁用触发器之外,您可以在此处执行的唯一操作是确保编写触发器以检查旧列和新列值以避免任何进一步的不必要更新。

  3. 您需要更改您的需求/程序,以便您需要旧的和新的实体值,以便您可以确定哪些列已更改而无需返回到数据库。

  4. 不要使用LINQ进行更新。 LINQ代表语言集成QUERY ,它是(恕我直言)在查询时非常出色,但我总是将更新/删除function视为额外的奖励,但不是它的设计目的。 此外,如果时序/性能至关重要,那么LINQ就无法正确匹配手工制作的SQL。

这不是一个DDD问题; 从我可以告诉你的问题:

使用linq生成直接更新而不选择

如果接受的答案是不可能的 ,那么更高的投票答案表明您可以对象附加到您的上下文以启动对数据上下文的更改跟踪。

关于禁用触发器的第二点已在此处和此处得到解答。 但是,正如其他人所评论的,你真的需要触发器吗? 您是否应该在代码中控制这些更新?

总的来说,我认为你正在考虑过早优化。 您正在使用ORM,并且作为您信任L2S的一部分,为您做出数据库管道决策。 但请记住,在适当的地方,您可以使用存储过程执行特定的SQL。