实体框架ObjectStateEntry,获取关系的属性

时间:2012-02-09 15:28:28

标签: c# entity-framework

我正在为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

感谢您的意见。

2 个答案:

答案 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