Take the 2-minute tour ×

I am working on a change analyzer for Entity Framework and have one small problem left.

I need to get the Property (PropertyInfo) of the parent in a relation (1-1, 1-n, n-n).

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. In my solution now, I use the EntitySet name from the related entity, but that just isn't good enough.

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.

Also, this code runs in DbContext.SaveChanges()


var objectContext = ((IObjectContextAdapter)this).ObjectContext;

var entityEntries = objectContext.ObjectStateManager
    .GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)

var relationEntries = objectContext.ObjectStateManager
    .GetObjectStateEntries(EntityState.Added | EntityState.Deleted)

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)
    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
            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. I would like to figure out the name of the property on the IHaveLogEntries entity instead if that is possible. That entity would be the combined.LogEntryEntity in this case.

Thankful for your input.

share|improve this question

1 Answer 1

up vote 0 down vote accepted

I've solved it now using the ObjectStateEntry.EntitySet property of the relationEntry that I had. 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.

Then I've added am Attribute so that I can decorate properties with better names if necessary.

This is what I added somewhere in the middle there:

let propertyName = relationEntry
let property = logEntryEntity
let nameAttribute = property
   .GetCustomAttributes(typeof(NameAttribute), true)
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.

share|improve this answer

Your Answer


