EF5如何获取域对象的导航属性列表

Ado*_*rez 4 entity-framework navigation-properties c#-4.0

我正在研究EF 5 Code-First解决方案,我正在尝试使用Repository模式更新现有实体并使用已修改的实体:

    public void UpdateValues(T originalEntity, T modifiedEntity)
    {
        _uow.Context.Entry(originalEntity).CurrentValues.SetValues(modifiedEntity);
Run Code Online (Sandbox Code Playgroud)

我的简化域对象如下所示:

public class PolicyInformation : DomainObject
{
     //Non-navigation properties
     public string Description {get;set;}
     public bool Reinsurance {get;set;}
     ...
     //Navigation properties
     LookupListItemFormType FormType {get;set;}
     ...
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是该CurrentValues.SetValues(modifiedEntity);方法似乎只更新标量和复杂类型属性,但不更新导航属性.我已经看到这种情况发生在很多人身上,但仍然不知道为什么会这样.但是,我发现如果我在执行后手动设置这些导航属性,UpdateValues一切正常:

            _policyInfoRepo.UpdateValues(existingPolicyInfo, info);
            existingPolicyInfo.FormType = info.FormType;
Run Code Online (Sandbox Code Playgroud)

问题是,因为我使用通用存储库:如何在域对象中获取导航属性列表?也许通过linq,反射或任何其他方式,以便我的存储库中的更新方法可以循环遍历它们并自动设置它们?

像这样的东西:

    public void UpdateValues(T originalEntity, T modifiedEntity)
    {
        //Set non-nav props
        _uow.Context.Entry(originalEntity).CurrentValues.SetValues(modifiedEntity);
        //Set nav props
        var navProps = GetNavigationProperties(originalEntity);
        foreach(var navProp in navProps)
        {
           //Set originalEntity prop value to modifiedEntity value
        }
Run Code Online (Sandbox Code Playgroud)

谢谢!

Bra*_*ley 6

我使用EF6编写了以下内容,但我相信它与EF5完全兼容.代码背后的一般思想是使用System.Data.Metadata.Edm中的优秀类来获取导航属性,并对这些属性名称使用反射来获取对象的真实属性以进行更新.

我想让我的例子尽可能通用但完整.在提问者的情况下,他显然会用"_uow.Context"替换"context".

public class MyClass<T> where T : class //T really needs to always be an entity, 
                                        //but I don't know a general parent type
                                        //for that. You could leverage partial classes
                                        //to define your own type.
{
    public MyEntities context { get; set; }

    public void UpdateValues(T originalEntity, T modifiedEntity)
    {
        //Set non-nav props
        context.Entry(originalEntity).CurrentValues.SetValues(modifiedEntity);
        //Set nav props
        var navProps = GetNavigationProperties(originalEntity);
        foreach (var navProp in navProps)
        {
            //Set originalEntity prop value to modifiedEntity value
            navProp.SetValue(originalEntity, navProp.GetValue(modifiedEntity));                
        }
    }

    public List<System.Reflection.PropertyInfo> GetNavigationProperties(T entity)
    {
        List<System.Reflection.PropertyInfo> properties = new List<System.Reflection.PropertyInfo>();
        //Get the entity type
        Type entityType = entity.GetType();
        //Get the System.Data.Entity.Core.Metadata.Edm.EntityType
        //associated with the entity.
        var entitySetElementType = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>().EntitySet.ElementType;
        //Iterate each 
        //System.Data.Entity.Core.Metadata.Edm.NavigationProperty
        //in EntityType.NavigationProperties, get the actual property 
        //using the entityType name, and add it to the return set.
        foreach (var navigationProperty in entitySetElementType.NavigationProperties)
        {
            properties.Add(entityType.GetProperty(navigationProperty.Name));
        }
        return properties;
    }
}
Run Code Online (Sandbox Code Playgroud)


Zev*_*itz 5

啊,LINQ(和using)的荣耀:

public List<PropertyInfo> GetNavigationProperties(T entity)
{
    var t = entity.GetType();
    var elementType = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>().EntitySet.ElementType;
    return elementType.NavigationProperties.Select(np => entityType.GetProperty(np.Name)).ToList();
}
Run Code Online (Sandbox Code Playgroud)

这也可以通过一种static方法实现,具有以下签名:

public static List<PropertyInfo> GetNavigationProperties<T>(DbContext context)
{
    var t = typeof(T);
    ...
Run Code Online (Sandbox Code Playgroud)