2

EntityFramework를 ORM으로 사용하고 값 개체 및 엔티티 개체 패턴 (Evans)을 나타내는 두 개의 기본 클래스가있는 간단한 POCO 도메인 모델을 사용합니다. 이 두 패턴은 모두 두 객체의 동등성에 관한 것이므로 Equals 및 GetHashCode 메서드를 오버라이드합니다. 다음은이 두 클래스는 다음과 같습니다 나는 "의 관계는 수 예외를 가지고 : 나는 (캐스케이드 삭제 표시가 된 두 개의 종속 개체로 집계 루트 개체) 일부 관련 개체를 삭제하려고 할 때까지Entity Framework 4.0 및 DDD 패턴

public abstract class EntityObject<T>{ 
     protected T _ID = default(T); 

     public T ID { 
      get { return _ID; } 
      protected set { _ID = value; } 
     } 

     public sealed override bool Equals(object obj) { 
      EntityObject<T> compareTo = obj as EntityObject<T>; 
      return (compareTo != null) && 
      ((HasSameNonDefaultIdAs(compareTo) || 
      (IsTransient && compareTo.IsTransient)) && 
      HasSameBusinessSignatureAs(compareTo)); 
     }  

     public virtual void MakeTransient() { 
      _ID = default(T);    

     } 

     public bool IsTransient { 
      get { 
       return _ID == null || _ID.Equals(default(T)); 
      } 
     } 

     public override int GetHashCode() { 
      if (default(T).Equals(_ID)) 
       return 0; 
      return _ID.GetHashCode(); 
     } 

     private bool HasSameBusinessSignatureAs(EntityObject<T> compareTo) { 
      return ToString().Equals(compareTo.ToString()); 
     } 

     private bool HasSameNonDefaultIdAs(EntityObject<T> compareTo) { 
      return (_ID != null && !_ID.Equals(default(T))) && 
      (compareTo._ID != null && !compareTo._ID.Equals(default(T))) && 
      _ID.Equals(compareTo._ID); 
     } 

     public override string ToString() { 
      StringBuilder str = new StringBuilder(); 
      str.Append(" Class: ").Append(GetType().FullName); 
      if (!IsTransient) 
       str.Append(" ID: " + _ID); 
      return str.ToString(); 
     } 
    } 

public abstract class ValueObject<T, U> : IEquatable<T> where T : ValueObject<T, U> { 
     private static List<PropertyInfo> Properties { get; set; } 
     private static Func<ValueObject<T, U>, PropertyInfo, object[], object> _GetPropValue; 

     static ValueObject() { 
      Properties = new List<PropertyInfo>();   
      var propParam = Expression.Parameter(typeof(PropertyInfo), "propParam"); 
      var target = Expression.Parameter(typeof(ValueObject<T, U>), "target"); 
      var indexPar = Expression.Parameter(typeof(object[]), "indexPar");    
      var call = Expression.Call(propParam, typeof(PropertyInfo).GetMethod("GetValue", new[] { typeof(object), typeof(object[]) }), 
       new[] { target, indexPar }); 
      var lambda = Expression.Lambda<Func<ValueObject<T, U>, PropertyInfo, object[], object>>(call, target, propParam, indexPar); 
      _GetPropValue = lambda.Compile();        
     } 

     public U ID { get; protected set; }   

     public override Boolean Equals(Object obj) { 
      if (ReferenceEquals(null, obj)) return false; 
      if (obj.GetType() != GetType()) return false; 
      return Equals(obj as T); 
     } 

     public Boolean Equals(T other) { 
      if (ReferenceEquals(null, other)) return false; 
      if (ReferenceEquals(this, other)) return true; 
      foreach (var property in Properties) { 
       var oneValue = _GetPropValue(this, property, null); 
       var otherValue = _GetPropValue(other, property, null); 
       if (null == oneValue && null == otherValue) return false; 
       if (false == oneValue.Equals(otherValue)) return false; 
      } 
      return true; 
     } 

     public override Int32 GetHashCode() { 
      var hashCode = 36; 
      foreach (var property in Properties) { 
       var propertyValue = _GetPropValue(this, property, null);    
       if (null == propertyValue) 
        continue; 
       hashCode = hashCode^propertyValue.GetHashCode(); 
      } 
      return hashCode; 
     } 

     public override String ToString() { 
      var stringBuilder = new StringBuilder(); 
      foreach (var property in Properties) { 
       var propertyValue = _GetPropValue(this, property, null); 
       if (null == propertyValue) 
        continue; 
       stringBuilder.Append(propertyValue.ToString()); 
      } 
      return stringBuilder.ToString(); 
     } 

     protected static void RegisterProperty(Expression<Func<T, Object>> expression) {   
      MemberExpression memberExpression; 
      if (ExpressionType.Convert == expression.Body.NodeType) { 
       var body = (UnaryExpression)expression.Body; 
       memberExpression = body.Operand as MemberExpression; 
      } 
      else 
       memberExpression = expression.Body as MemberExpression; 
      if (null == memberExpression) 
       throw new InvalidOperationException("InvalidMemberExpression");   
      Properties.Add(memberExpression.Member as PropertyInfo); 
     } 
    } 

모든 OK이었다 하나 이상의 외래 키 등록 정보가 null이 허용되지 않기 때문에 변경되지 않습니다. " 내가 봤 거든 찾았 어 http://blog.abodit.com/2010/05/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-properties-is-non-nullable/ 나는 GetHashCode을 base.GetHashCode()로 변경했고 오류가 사라졌다. 하지만 이제는 내 모든 코드가 깨졌습니다. POCO 객체에 대해 GetHashCode를 재정의 할 수 없습니다. => Equals => 재정의 할 수 없습니다.> POCO 객체에 대한 값 객체 및 객체 객체 패턴을 구현할 수 없습니다. 따라서 솔루션, 해결 방법 등을 고맙게 생각합니다.

답변

0

GetHashCode를 재정의하려면 직접 문제를 해결해야합니다. 문제의 SAIS는 :

"The relationship could not be changed because one or more of the foreign-key properties is non-nullable" 

그래서,
1. 외래 키로 사용되는 널 (NULL) 입력이 가능하지 필드를 찾아서이 널 (그래서 당신은 기록을 삭제할 경우 - FK는 null도 가능)를 확인하십시오.
2. 종속성을 계단식 삭제로 표시하지 마십시오.

관련 문제