我正在尝试在我们的上下文中克隆实体。除了多对多表以外,其他一切都正常。
这是层次结构:
“资金”表将“贡献流”链接到“目标”。一个缺陷是资金行具有FundingId,ContributionStreamId和GoalId。我不知道使用后两个作为主键。
我正在尝试复制计划以及所有较低级别的实体。根据{{3}},我分离了计划并更新了ID,但是Fundings表中新的“多对多”条目指向新的ContributionStreams和旧目标
这是代码
var detachedPlan = db.Plans
.Include("Goals")
.Include("Accounts")
.Include("Accounts.ContributionStreams")
.Include("Accounts.ContributionStreams.Fundings").AsNoTracking()
.FirstOrDefault(p => p.PlanId == originalPlan.PlanId);
foreach (var goal in detachedPlan.Goals.ToList())
{
Guid newGoalId = Guid.NewGuid();
goal.GoalId = newGoalId;
}
foreach (var account in detachedPlan.Accounts.ToList())
{
account.AccountId = Guid.NewGuid();
foreach (var contributionStream in account.ContributionStreams.ToList())
{
Guid newContributionStreamId = Guid.NewGuid();
var fundingList = contributionStream.Fundings.ToList();
contributionStream.ContributionStreamId = newContributionStreamId;
foreach (Funding funding in fundingList)
{
funding.ContributionStreamId = newContributionStreamId;
funding.FundingId = Guid.NewGuid();
}
}
}
detachedPlan.PlanId = Guid.NewGuid();
detachedPlan.Name += " copy";
db.Plans.Add(detachedPlan);
您可以看到,除了替换主键funding.ContributionStreamId = newContributionStreamId;
之外,我还必须创建从Funding到ContributionStream的引用。对目标进行类似的分配会创建不需要的实体副本,它们指向旧目标,而不是新的tributionStream。
Fundings类是从数据库自动生成的:
public partial class Funding
{
public System.Guid FundingId { get; set; }
public System.Guid ContributionStreamId { get; set; }
public System.Guid GoalId { get; set; }
public double Weight { get; set; }
public string Notes { get; set; }
public virtual ContributionStream ContributionStream { get; set; }
public virtual Goal Goal { get; set; }
}
“资金的SQL”是
CREATE TABLE [dbo].[Fundings] (
[FundingId] UNIQUEIDENTIFIER NOT NULL,
[ContributionStreamId] UNIQUEIDENTIFIER NOT NULL,
[GoalId] UNIQUEIDENTIFIER NOT NULL,
[Weight] FLOAT NOT NULL DEFAULT 1,
[Notes] NVARCHAR(4000) NULL,
PRIMARY KEY CLUSTERED ([FundingId] ASC),
CONSTRAINT [FK_Fundings_ContributionStreams] FOREIGN KEY ([ContributionStreamId]) REFERENCES [dbo].[ContributionStreams] ([ContributionStreamId]) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT [FK_Fundings_Goals] FOREIGN KEY ([GoalId]) REFERENCES [dbo].[Goals] ([GoalId])
);
答案 0 :(得分:0)
好吧,我决定采用下面的“强力”解决方案。我仍然不了解为什么我无法更新创建新的target.GoalId的循环中的funding.GoalId的内部原理。无知不是幸福。
这是解决方案
// Keep track of the mapping of old goals to new goals
Dictionary<Guid, Guid> oldGoalId = new Dictionary<Guid, Guid>();
var detachedPlan = db.Plans
.Include("Goals")
.Include("Accounts")
.Include("Accounts.ContributionStreams")
.Include("Accounts.ContributionStreams.Fundings").AsNoTracking()
.FirstOrDefault(p => p.PlanId == originalPlan.PlanId);
foreach (var goal in detachedPlan.Goals.ToList())
{
Guid newGoalId = Guid.NewGuid();
oldGoalId.Add(goal.GoalId, newGoalId); // record old and new goalId for the new goal
// BTW, this seems like the right solution, but it's not.
// This loop creates unwanted additional copies of the funding in the old Plan
// foreach (Funding funding in goal.Fundings.ToList())
// funding.GoalId = newGoalId;
goal.GoalId = newGoalId;
}
foreach (var account in detachedPlan.Accounts.ToList())
{
account.AccountId = Guid.NewGuid();
foreach (var contributionStream in account.ContributionStreams.ToList())
{
Guid newContributionStreamId = Guid.NewGuid();
var fundingList = contributionStream.Fundings.ToList();
contributionStream.ContributionStreamId = newContributionStreamId;
foreach (Funding funding in fundingList)
{
funding.ContributionStreamId = newContributionStreamId;
// update the GoalId here.
// Not sure why it can't be updated in the commented out loop above
funding.GoalId = oldGoalId[funding.GoalId];
funding.FundingId = Guid.NewGuid();
}
}
}
detachedPlan.PlanId = Guid.NewGuid();
detachedPlan.Name += " copy";
db.Plans.Add(detachedPlan);