0

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

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

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

2)它需要更新所有的列(不仅仅是改变的列)。这是因为我们不知道域对象中的所有列都发生了什么变化。

如何克服这些缺点?

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

参考

  1. LINQ to SQL:在“UpdateCheck = Never”时更新而不刷新</a>

  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<DBML_Project.BankAccount>().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";
    }
}


}
4

2 回答 2

1

这不是一个真正的 DDD 问题。据我所知,你在问:

使用 linq 生成直接更新,无需选择

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

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

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

于 2012-06-30T06:24:52.073 回答
1

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

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

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

  2. 您需要避免选择并只更新列。您已经知道该怎么做(但其他人请参阅此问题和答案)。由于您不知道哪些列已更改,因此您别无选择,只能将它们全部设置。即使没有实际更改任何列,这也会产生一条更新语句,并且这可以触发任何数据库触发器。除了禁用触发器之外,您在这里唯一能做的就是确保编写触发器以检查旧列和新列的值,以避免任何进一步的不必要的更新。

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

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

于 2012-06-30T11:09:19.320 回答