gpt4 book ai didi

entity-framework - Entity Framework : Tracking changes to FK associations

转载 作者:行者123 更新时间:2023-12-04 12:56:10 25 4
gpt4 key购买 nike

我在我的 DbContext 上覆盖 SaveChanges 以实现审核日志。处理多对多关系或独立关联相对容易,因为 EF 会为这些类型的关系的任何更改创建 ObjectStateEntries。

我正在使用外键关联,当实体之间的关系发生变化时,您得到的只是一个 ObjectStateEnty,例如实体“Title”的“PublisherID”属性已更改。对于人类来说,这显然是 Title 实体中的外键,但我如何在运行时确定它?有没有办法将此更改转换为“PublisherID”属性,以便为外键表示的实体提供一个 EntityKey?

我假设我正在处理看起来像这样的实体:

public sealed class Publisher
{
public Guid ID { get; set; }
public string Name { get; set; }
public ICollection<Title> Titles { get; set; }
}

public class Title
{
public Guid ID { get; set; }
public string Name { get; set; }
public Guid? PublisherID { get; set; }
public Publisher Publisher { get; set; }
}

还有定义关系和外键的 EF EntityConfiguration 代码:
public TitleConfiguration()
{
HasOptional<Publisher>(t => t.Publisher).WithMany(
p => p.Titles).HasForeignKey(t => t.PublisherID);
}

我现在正在做的事情似乎有点太复杂了。我希望有更优雅的方式来实现我的目标。对于来自 ObjectStateEntry 的每个修改过的属性,我查看当前实体的所有 ReferentialConstraints 并查看是否有任何将其用作外键。下面的代码是从 SaveChanges() 调用的:
private void HandleProperties(ObjectStateEntry entry, 
ObjectContext ctx)
{
string[] changedProperties = entry.GetModifiedProperties().ToArray();
foreach (string propertyName in changedProperties)
{
HandleForeignKey(entry, ctx, propertyName);
}
}

private void HandleForeignKey(ObjectStateEntry entry,
ObjectContext ctx, string propertyName)
{
IEnumerable<IRelatedEnd> relatedEnds =
entry.RelationshipManager.GetAllRelatedEnds();

foreach (IRelatedEnd end in relatedEnds)
{
// find foreign key relationships
AssociationType elementType = end.RelationshipSet.ElementType as
AssociationType;
if (elementType == null || !elementType.IsForeignKey) continue;

foreach (ReferentialConstraint constraint in
elementType.ReferentialConstraints)
{
// Multiplicity many means we are looking at a foreign key in a
// dependent entity
// I assume that ToRole will point to a dependent entity, don't
// know if it can be FromRole
Debug.Assert(constraint.ToRole.RelationshipMultiplicity ==
RelationshipMultiplicity.Many);
// If not 1 then it is a composite key I guess.
// Becomes a lot more difficult to handle.
Debug.Assert(constraint.ToProperties.Count == 1);
EdmProperty prop = constraint.ToProperties[0];

// entity types of current entity and foreign key entity
// must be the same
if (prop.DeclaringType == entry.EntitySet.ElementType
&& propertyName == prop.Name)
{
EntityReference principalEntity = end as EntityReference;
if (principalEntity == null) continue;

EntityKey newEntity = principalEntity.EntityKey;
// if there is more than one, the foreign key is composite
Debug.Assert(newEntity.EntityKeyValues.Length == 1);

// create an EntityKey for the old foreign key value
EntityKey oldEntity = null;

if (entry.OriginalValues[prop.Name] is DBNull)
{
oldEntity = new EntityKey();
oldEntity.EntityKeyValues = new[] {
new EntityKeyMember("ID", "NULL")
};
oldEntity.EntitySetName = newEntity.EntitySetName;
}
else
{
Guid oldGuid = Guid.Parse(
entry.OriginalValues[prop.Name].ToString());
oldEntity = ctx.CreateEntityKey(newEntity.EntitySetName,
new Publisher()
{
ID = oldGuid
});
}

Debug.WriteLine(
"Foreign key {0} changed from [{1}: {2}] to [{3}: {4}]",
prop.Name,
oldEntity.EntitySetName, oldEntity.EntityKeyValues[0],
newEntity.EntitySetName, newEntity.EntityKeyValues[0]);
}
}
}
}

我希望这有助于更好地说明我正在努力实现的目标。欢迎任何意见。

谢谢!

最佳答案

看起来我的代码是解决这个问题的正确方法:/

我确实最终使用了独立的协会来完全避免这个问题。

关于entity-framework - Entity Framework : Tracking changes to FK associations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6048921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com