C# 更新父表的任何其他最佳方式';当更新子表时,是否为s列?

C# 更新父表的任何其他最佳方式';当更新子表时,是否为s列?,c#,sql,sql-server,database-trigger,C#,Sql,Sql Server,Database Trigger,我有几个表结构,如下所示: CREATE TABLE Person ( PersonID INT PRIMARY KEY, Name NVARCHAR(255), LastUpdatedBy INT, LastUpdatedDate DATETIME ); CREATE TABLE Info ( InfoID INT PRIMARY KEY, PersonID INT, Info NVARCHAR(255), LastUpdate

我有几个表结构,如下所示:

CREATE TABLE Person
(
    PersonID INT PRIMARY KEY,
    Name NVARCHAR(255),
    LastUpdatedBy INT,
    LastUpdatedDate DATETIME
);

CREATE TABLE Info
(
    InfoID INT PRIMARY KEY,
    PersonID INT,
    Info NVARCHAR(255),
    LastUpdatedBy INT,
    LastUpdatedDate DATETIME
);

CREATE TABLE Setting
(
    SettingID INT PRIMARY KEY,
    PersonID INT,
    Setting NVARCHAR(255),
    LastUpdatedBy INT,
    LastUpdatedDate DATETIME
);
我将面临一个新的过程,若信息或设置表有任何更新,我将需要对LastUpdateBy和LastUpdateDate列上的Person表进行相关更新

我首先想到的是创建一个SQL触发器,当Info或SETING table执行此操作时,它会自动更新Person表。但请快速浏览几篇文章,其中指出应避免使用SQL触发器,因为在创建它时这是一个非常昂贵的过程

而有些人建议更改应用程序代码。比如,

using (var db = new DbContext())
{
    var result = db.Info.SingleOrDefault(x => x.InfoID == infoID);
    if (result != null)
    {
        result.Info = "Some new value";
        result.LastUpdatedBy = userID;
        result.LastUpdatedDate = DateTime.UtcNow;
        db.SaveChanges();
    }
}
需要改变,变成这样

using (var db = new DbContext())
{
    var result = db.Info.SingleOrDefault(x => x.InfoID == infoID);
    if (result != null)
    {
        result.Info = "Some new value";
        result.LastUpdatedBy = userID;
        result.LastUpdatedDate = DateTime.UtcNow;

        var person = db.Person.SingleOrDefault(x => x.PersonID == result.PersonID);
        if (person != null)
        {
            person.LastUpdatedBy = result.LastUpdatedBy;
            person.LastUpdatedDate = result.LastUpdatedDate;
        }
        db.SaveChanges();
    }
}
实际上,应用程序代码是海量的,需要进行大量的代码修改

假设有30多个表,每个表至少包含100k条记录。如果可以创建触发器,则如下所示:

CREATE TRIGGER TriggerName ON dbo.Info
    AFTER INSERT, UPDATE
AS
    BEGIN 
        SET NOCOUNT ON;
        UPDATE  dbo.Person
        SET     LastUpdatedBy = INSERTED.LastUpdatedBy ,
                LastUpdatedDate = INSERTED.LastUpdatedDate
        FROM    INSERTED
        WHERE   dbo.Person.PersonID = INSERTED.PersonID
    END 
GO 
在这种情况下是否真的应该避免使用SQL触发器?如果可以,请根据您的回答进行解释。欢迎任何替代解决方案,性能第一。

触发器在这里是最佳的(从性能角度来看);这就像在前端代码的一堆行上运行update语句一样。我不明白你为什么认为会有表现惩罚。不过,您的触发器代码应该更像这样:

CREATE TRIGGER TriggerName ON dbo.Info
AFTER INSERT, UPDATE
AS
BEGIN 
    SET NOCOUNT ON;
    UPDATE  dbo.Person
    SET     LastUpdatedBy = INSERTED.LastUpdatedBy ,
            LastUpdatedDate = INSERTED.LastUpdatedDate
    FROM    dbo.Person 
            INNER JOIN 
            INSERTED
            ON dbo.Person.PersonID = INSERTED.PersonID
END 
GO 
还有其他方法,例如生成更新事务中所有表的存储过程,或者更新前端数据访问层(如果你的前端有很多东西要更新,这意味着它的结构是错误的:一个地方应该负责写入这个表。如果你的前端代码有贯穿其中的update语句,那么..这是一个糟糕的设计)所以一个专用类正确地维护这两个表


现在我想说,触发器是解决问题的最简单方法。它们不受欢迎,虽然不是因为性能,而是因为它们开始增加令人困惑的后果。想象一下,你是一个数据库经验有限的c#开发人员,不知道触发器是什么,你在抱怨“每次我只更新这一个表时,所有其他27个表都会发生神奇的变化!发生了什么事?我疯了还是怎么了?”-触发器会打破规则,如“将所有数据更新代码保留在一个位置”"这就是为什么设计特定部件具有特定作业的系统的人不喜欢触发器的原因。

触发器是可以的。每个
UPDATE
语句调用一次触发器,即使
UPDATE
影响多行。顺便提一下,这就是问题中的触发器代码错误的原因-当多行被更新时,它将失败。如果您ix触发器代码它可以正常工作。触发器是高度特定于供应商的-因此请添加一个标记,以指定您使用的是
mysql
postgresql
sql server
oracle
db2
-还是其他完全不同的东西。@marc_假定sql server由于未设置计数,因此进行了相应的标记