在实体框架中更新具有子记录标识的父记录

时间:2013-11-15 17:42:27

标签: entity-framework transactionscope

我有两张桌子,父母和孩子。两者都有一个autoincrement indentity字段作为主键。 Child有一个包含父级ID的字段,并且有一个FK强制执行该关系。

Parent有一个包含最新孩子ID的字段。

CREATE TABLE parent
(
    parentid int IDENTITY(1,1) NOT NULL,
    latestchildid int,
    parentdata nvarchar(256),
    CONSTRAINT PK_parent PRIMARY KEY CLUSTERED 
    (
        parentid
    )
)

CREATE TABLE child
(
    parentid int,
    childid int IDENTITY(1,1) NOT NULL,
    childdata nvarchar(256),
    CONSTRAINT PK_child PRIMARY KEY CLUSTERED 
    (
        parentid,
        childid
    )
)

ALTER TABLE child
ADD  CONSTRAINT FK_child_parent
FOREIGN KEY (parentid)
REFERENCES parent (parentid)

public partial class parent
{
    public int parentid { get; set; }
    public int latestchildid { get; set; }
    public string parentdata { get; set; }

    public virtual ICollection<child> child {get; set; }
}

public partial class child
{
    public int parentid { get; set; }
    public int childid { get; set; }
    public string childdata { get; set; }

    public virtual parent { get; set; }
}

如何在单个交易中插入新的父记录和新的子记录,并更新父记录中的最新子字段?

什么有效:

var parent = new parent
    {
        parentdata = "Some info about a parent"
    };

var child = new child
    {
        childdata = "Some info about a child"
    };

parent.child.Add(child);
dbContext.parents.Add(parent);
dbContext.SaveChanges();

parent.latestchildid = child.childid;
dbContext.SaveChanges();

这个问题是它需要两个交易。

但是如果我将它全部包装在TransactionScope中,那么只要EF决定对各个部分使用不同的连接(这是一个几乎不受我们控制的决定),它就会将事务提升为分布式,这需要MSDTC可在用户计算机和数据库主机上配置并运行。这是一种彻头彻尾的恶化。

那么,我可以获取childid的值,并将其写入父级,而不必两次调用SaveChanges()吗?

或者我可以以某种方式强制EF使用单个连接,对于此事务,以便它不会将其提升为分布式?

1 个答案:

答案 0 :(得分:0)

使用latestchildid作为主键

为父级和子级之间的外键关系创建另一个约束

然后添加到您的父类public virtual child latestchild {get; set; }

然后在第一次保存更改parent.latestchild = child;

之前添加新分配

删除分配的最后两行并重新保存