我正在为Entity Framework开发一个更改分析器,但还有一个小问题。
我需要在关系(1-1,1-n,n-n)中获取父项的属性(PropertyInfo
)。
现在我可以看到关系,父项和相关条目,但我似乎无法获得该对象的实际属性。我看到的问题是关系知道关键字,PK和FK,而不是首先负责关系的属性。在我的解决方案中,我使用相关实体的EntitySet名称,但这还不够好。
这是解决关系的代码。我遗漏了实体对象以及非关系分析部分。 IHaveLogEntries
接口将在想要分析的实体上实现。
此外,此代码在DbContext.SaveChanges()
this.ChangeTracker.DetectChanges();
var objectContext = ((IObjectContextAdapter)this).ObjectContext;
var entityEntries = objectContext.ObjectStateManager
.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
.ToList();
var relationEntries = objectContext.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Deleted)
.ToList();
var q = from relationEntry in relationEntries
from entityEntry in entityEntries
where relationEntry.IsRelationshipForKey(entityEntry.EntityKey)
where !(entityEntry.Entity is IHaveLogEntries)
let otherEndKey = relationEntry.OtherEndKey(entityEntry.EntityKey)
let logEntryEntity = entityEntries
.Where(e => e.EntityKey == otherEndKey)
.Select(se => se.Entity)
.Cast<IHaveLogEntries>()
.Single()
let combined = new
{
RelationEntry = relationEntry,
EntityEntry = entityEntry,
LogEntryEntity = logEntryEntity
}
group combined by
new { combined.LogEntryEntity, combined.EntityEntry.EntitySet.Name }
into combinedGroup
let added = combinedGroup
.Where(c => c.RelationEntry.State == EntityState.Added)
.Select(c => c.EntityEntry.Entity.ToString())
let deleted = combinedGroup
.Where(c => c.RelationEntry.State == EntityState.Deleted)
.Select(c => c.EntityEntry.Entity.ToString())
select new
{
combinedGroup.Key.LogEntryEntity,
Field = combinedGroup.Key.Name,
Operation = Operation.Modified,
FromValue = (object)string.Join(",", deleted.ToArray()),
ToValue = (object)string.Join(",", added.ToArray())
};
var l = q.ToList();
主要问题是我对结果进行分组,我使用combined.EntityEntry.EntitySet.Name
。我想在IHaveLogEntries
实体上找出属性的名称,如果可能的话。在这种情况下,该实体将是combined.LogEntryEntity
。
感谢您的意见。
答案 0 :(得分:0)
我现在使用我拥有的relationEntry的ObjectStateEntry.EntitySet
属性解决了它。有了这个,我可以看到像 Entity_Property 之类的关系的名称,我只是在那里对属性名称进行字符串提取,然后我用它来从PropertyInfo对象>实体强>
然后我添加了am属性,以便在必要时可以使用更好的名称来修饰属性。
这是我在中间的某处添加的内容:
let propertyName = relationEntry
.EntitySet
.Name
.Split("_".ToCharArray())
.Last()
let property = logEntryEntity
.GetType()
.GetProperty(propertyName)
let nameAttribute = property
.GetCustomAttributes(typeof(NameAttribute), true)
.Cast<NameAttribute>()
.FirstOrDefault()
let name = nameAttribute != null ? nameAttribute.Name : property.Name
然后我使用名称进行分组:
let combined = new {
FieldName = name,
RelationEntry = relationEntry,
EtityEntry = entityEntry,
LogEntryEntity = logEntryEntity
}
group combined by new { combined.LogEntryEntity, combined.FieldName }
into combinedGroup
到目前为止似乎确实有效,尽管我想知道是否有人有更好的想法。字符串管理感觉有点狡猾。
答案 1 :(得分:0)
我知道这个问题很老,但其他人可能会从此信息中受益。我有同样的问题要解决,不想依靠字符串解析。我发现实际的PropertyInfo在这里:
(PropertyInfo)objectStateEntry.EntitySet.ElementType.Members[0].MetadataProperties["ClrPropertyInfo"].Value