2013-07-26 4 views
3

에 대한 탐색 속성의 목록을 얻기 위해 나는 저장소 패턴을 사용하여 수정 된 하나 기존 엔티티 업데이트하려고 방법 :EF5 내가 EF 5 코드 - 첫 번째 솔루션에서 일하고 있어요 도메인 오브젝트

public void UpdateValues(T originalEntity, T modifiedEntity) 
    { 
     _uow.Context.Entry(originalEntity).CurrentValues.SetValues(modifiedEntity); 

내 단순화 된 도메인 객체는 다음과 같습니다 : 내가 가지고있는

public class PolicyInformation : DomainObject 
{ 
    //Non-navigation properties 
    public string Description {get;set;} 
    public bool Reinsurance {get;set;} 
    ... 
    //Navigation properties 
    LookupListItemFormType FormType {get;set;} 
    ... 
} 

문제는 CurrentValues.SetValues(modifiedEntity); 방법은 스칼라 복잡한 종류의 호텔이 아니라 탐색 속성을 업데이트 할 것으로 보인다는 것이다. 나는 많은 사람들에게 이런 일이 일어난 것을 보았지만 그 이유는 아직도 모른다. 나는 일반적인 저장소를 사용하기 때문에

  _policyInfoRepo.UpdateValues(existingPolicyInfo, info); 
      existingPolicyInfo.FormType = info.FormType; 

이 문제가된다 : 그러나, 나는 내 UpdateValues 모든 것을 실행 한 후 수동으로 그 탐색 속성을 설정하면 잘 작동하는지 알아 냈 어떻게에서 탐색 속성의 목록을 얻을 수 있습니다 내 도메인 개체? 아마도 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 
     } 

감사합니다!

답변

6

나는 EF6를 사용하여 다음과 같이 썼다. 그러나 나는 그것이 모두 EF5와 호환된다고 생각한다. 코드 뒤에 나오는 일반적인 생각은 a System.Data.Metadata.Edm의 우수한 클래스를 사용하여 탐색 속성을 가져오고 해당 속성 이름에 반영을 사용하여 업데이트 할 개체의 실제 속성을 가져 오는 것입니다.

나는 가능한 한 완벽하고 포괄적 인 것으로 내 사례를 만들고 싶었습니다. Asker의 경우, 그는 "context"를 "_uow.Context"로 바꾸었다. LINQ (및 using)의

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; 
    } 
} 
4

아 영광은 : ZEV의 기준

public static List<PropertyInfo> GetNavigationProperties<T>(DbContext context) 
{ 
    var t = typeof(T); 
    ... 
3

:

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(); 
} 

이는 또한 다음 서명하는 static 방법을 통해 구현 될 수있다 답변 :

public List<PropertyInfo> GetNavigationProperties<T>(DbContext context) where T : class 
{ 
    var entityType = typeof(T); 
    var elementType = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>().EntitySet.ElementType; 
    return elementType.NavigationProperties.Select(property => entityType.GetProperty(property.Name)).ToList(); 
} 
+0

우리는 'CrowdWorxEntities'가 무엇인지 알고 있어야합니까? –

+0

그것은 DbContext ..입니다. –

2
public static T Clone<T>(this T entity) where T : class 
    { 
     var type = entity.GetType(); 
     var clone = Activator.CreateInstance(type); 

     var navigationProperties = type.GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.DeclaredOnly); 

     foreach (var property in type.GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty)) 
     { 
      //if (property.Module.ScopeName == "EntityProxyModule") continue; 
      if (navigationProperties.Contains(property)) continue; 

      if (property.CanWrite) 
      { 
       property.SetValue(clone, property.GetValue(entity, null), null); 
      } 
     } 

     return (T)clone; 
    } 

BindingFlags.DeclaredOnly를 사용하면 탐색 속성 만 동적 프록시에 직접 정의되므로 필터링 속성을 필터링 할 수 있습니다.

네비게이션 속성의 경우 property.Module.ScopeName을 사용하여 네비게이션 속성을 구분합니다.이 값은 "EntityProxyModule"이지만 다른 속성의 경우이 값은 정의한 프로젝트의 dll 이름입니다. EF 코드의 첫 번째 도메인 클래스

이 Clone 메서드를 사용하여 순환 참조를 피하기 위해 EF 코드 첫 번째 도메인 개체를 복제하지만 (순환 참조는 피함) 탐색 속성 목록을 가져 오는 방법에 대한 작성자의 쿼리가 포함되어 있습니다. 이내에.