简体   繁体   English

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

[英]Entity Framework ObjectStateEntry, get property of relation

I am working on a change analyzer for Entity Framework and have one small problem left.我正在为 Entity Framework 开发一个变更分析器,但还剩下一个小问题。

I need to get the Property ( PropertyInfo ) of the parent in a relation (1-1, 1-n, nn).我需要在关系 (1-1, 1-n, nn) 中获取父项的属性 ( PropertyInfo )。

Right now I can see the relation, the parent and the related entries, but I cannot seem to get the actual property of the object.现在我可以看到关系、父项和相关条目,但我似乎无法获得对象的实际属性。 The problem as I see it is that the relation knows about the keys, which are PKs and FKs and not the property that was responsible for the relation in the first place.我看到的问题是关系知道键,它们是 PK 和 FK,而不是首先负责关系的属性。 In my solution now, I use the EntitySet name from the related entity, but that just isn't good enough.在我现在的解决方案中,我使用来自相关实体的 EntitySet 名称,但这还不够好。

Here is the code that resolves the relations.这是解决关系的代码。 I've left out the entity objects as well as the non relational analyzing parts.我已经遗漏了实体对象以及非关系分析部分。 The IHaveLogEntries interface is to be implemented on Entities that want to be analyzed. IHaveLogEntries接口将在要分析的实体上实现。

Also, this code runs in DbContext.SaveChanges()此外,此代码在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();

The main problem is where I group the result, where I use combined.EntityEntry.EntitySet.Name .主要问题是我在哪里对结果进行分组,在那里我使用combined.EntityEntry.EntitySet.Name I would like to figure out the name of the property on the IHaveLogEntries entity instead if that is possible.如果可能的话,我想找出IHaveLogEntries实体上的属性名称。 That entity would be the combined.LogEntryEntity in this case.在这种情况下,该实体将是combined.LogEntryEntity的.LogEntryEntity。

Thankful for your input.感谢您的投入。

I know this question is very old but someone else might benefit from this info.我知道这个问题很老了,但其他人可能会从这些信息中受益。 I had the same issue to solve and didn't want to rely on string parsing.我有同样的问题要解决,不想依赖字符串解析。 I've found the actual PropertyInfo is here:我发现实际的 PropertyInfo 在这里:

(PropertyInfo)objectStateEntry.EntitySet.ElementType.Members[0].MetadataProperties["ClrPropertyInfo"].Value

I've solved it now using the ObjectStateEntry.EntitySet property of the relationEntry that I had.我现在使用我拥有的relationEntry 的ObjectStateEntry.EntitySet属性解决了它。 With that, I can see the name of the relation like this Entity_Property and I simply do a string extraction of the property name there which I then use to get the PropertyInfo object from the Entity .有了这个,我可以看到像这个Entity_Property这样的关系的名称,我只是在那里对属性名称进行字符串提取,然后我用它从Entity获取PropertyInfo对象。

Then I've added am Attribute so that I can decorate properties with better names if necessary.然后我添加了 am Attribute 以便我可以在必要时用更好的名称装饰属性。

This is what I added somewhere in the middle there:这是我在中间某处添加的内容:

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

I then use the name to group on instead:然后我使用名称进行分组:

let combined = new {
   FieldName = name,
   RelationEntry = relationEntry,
   EtityEntry = entityEntry,
   LogEntryEntity = logEntryEntity
}
group combined by new { combined.LogEntryEntity, combined.FieldName } 
   into combinedGroup

It does seem to work so far, even though I would like to know if anyone has a better idea.到目前为止,它似乎确实有效,尽管我想知道是否有人有更好的主意。 The string management feels a bit dodgy.字符串管理感觉有点狡猾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM