2011-04-20 1 views
1

Money에 대한 사용자 지정 형식을 POCO와 함께 사용하고이를 데이터베이스에 삽입하려고 시도했지만 이 Entity Framework에 의해 버려졌습니다.EF 4.1 사용자 정의 형식 처리 돈 사용

이것은 간단한 코드입니다.

내 유형;

public struct Money 
{ 
    private static decimal _value; 

    public Money(Decimal value) 
    { 
     _value = value; 
    } 

    public static implicit operator Money(Decimal value) 
    { 
     return new Money(value); 
    } 

    public static implicit operator decimal(Money value) 
    { 
     return _value; 
    } 
} 

내 개체;

public class MyObject 
{ 
    [Key] 
    public int Id { get; set; } 
    public Money MyMoney { get; set; } 
} 

내 컨텍스트;

public class Data : DbContext 
{ 
    public Data() 
     : base("Data Source=.;Database=MyTest;Integrated Security=True") 
    {} 

    public DbSet<MyObject> MyObject { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 

     modelBuilder.Entity<MyObject>() 
      .Property(p => p.MyMoney).HasColumnName("MyMoney"); 

    } 
} 

이 코드를 사용할 때 다음과 같은 오류가 발생합니다.

'MyMoney'속성은 'MyObject'유형의 신고 된 속성이 아닙니다. 무시 방법 또는 NotMappedAttribute 데이터 주석을 사용하여 에 의해 모델에서 명시 적으로 제외 된 속성이 인지 확인합니다. 유효한 원시 (primitive) 속성인지 확인하십시오.

마지막 문장이 문제 인 것 같군요. 그렇다면 유효한 원시 속성은 무엇입니까? 이 문제를 처리 할 다른 방법이 있습니까?

+0

Per, 아마도 도움이 될 수 있습니다. http : // stackoverflow.co.kr/q/6794565/828162 – iuristona

답변

1

좋아, 이건 내 솔루션으로 갔다.

public class MyObject 
{ 
    [Key] 
    public int Id { get; set; } 
    public Money MyMoney { get { return (Money)MyMoneyInternal; } set { MyMoneyInternal = (decimal)value; } } 
    private decimal MyMoneyInternal { get; set; } 
} 

내가 다음과 같이 특성 확장을 만들어 그 사유 재산을 읽을 수합니다. Money 유형의 일부 속성이 Nullable이므로이 또한 처리해야했습니다.

public static class PropertyExtensions 
{ 
    public static PrimitivePropertyConfiguration Property<TClass, TProperty>(this EntityTypeConfiguration<TClass> etc, string propertyName) 
     where TClass : class 
     where TProperty : struct 
    { 
     PrimitivePropertyConfiguration returnValue; 
     Type type = typeof(TClass); 

     var propertyInfo = type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 

     ParameterExpression parameterExpression = Expression.Parameter(type, "xyz"); 
     MemberExpression memberExpression = Expression.Property((Expression)parameterExpression, propertyInfo); 

     if (IsNullable(memberExpression.Type)) 
     { 
      returnValue = etc.Property((Expression<Func<TClass, TProperty?>>)Expression.Lambda(memberExpression, parameterExpression)); 
     } 
     else 
     { 
      returnValue = etc.Property((Expression<Func<TClass, TProperty>>)Expression.Lambda(memberExpression, parameterExpression)); 
     } 

     return returnValue; 
    } 

    private static bool IsNullable(Type type) 
    { 
     bool result; 

     if (type.IsGenericType) 
     { 
      var genericType = type.GetGenericTypeDefinition(); 
      result = genericType.Equals(typeof(Nullable<>)); 
     } 
     else 
     { 
      result = false; 
     } 

     return result; 
    } 
} 

그리고 나서 내 개인 재산을 읽을 수 있습니다.

modelBuilder.Entity<MyObject>() 
      .Property<MyObject, decimal>("MyMoneyInternal").HasColumnName("MyMoney"); 

스티브에게 올바른 방향으로 데려다 주셔서 감사합니다.

3

당신은 명시 적으로 소수 속성을 매핑 만 호출자에 Money 속성을 노출하여 그것을 걸릴 수 :

public class MyObject 
{ 
    [Key] 
    public int Id { get; set; } 
    protected decimal MyMoney { get; set; } 
    public Money MyMoneyStruct 
    { 
     get { return (Money)this.MyMoney; } 
     set { this.MyMoney = (decimal)value; } 
    } 
} 
+0

+1. EF는 스칼라 사용자 유형을 지원하지 않습니다. –

+1

좋습니다. Unfortunatelly code-first는 protected 필드와 private 필드를 매핑하지 않습니다. 이것을 극복하기 위해서는 엔티티 프로젝트 EF에 의존하는 각 엔티티에서 중첩 된'EntityConfiguration'을 사용해야합니다. –

+0

@Ladislav, 고마워, 나는 그걸 몰랐다. 그것은 내가 보호 된 필드를 허용 할 것으로 기대하는 것 같은 일종의 감독처럼 보입니다. 오 잘. 내가 설명했듯이 둘 다 항상 노출되거나 EntityConfiguration을 사용할 수 있다고 가정합니다. –

0

"돈"을 복잡한 클래스로 변환 할 수도 있습니다. 이는 데이터베이스에서 노출 된 속성을 인라인으로 만듭니다. Decimal 속성 만 있으면 Money_Value처럼 보일 것입니다 (Value가 속성으로 제공된 경우). 클래스에 "Currency"를 문자열로 추가한다고 가정 해 보겠습니다. 그런 다음 데이터베이스에 Money_Currency도 갖게됩니다.

EF에 클래스가 복합 유형임을 선언하려면 [ComplexType()]으로 주석을 달아주세요.

Struct + ComplexType의 장점을 최대한 활용하려면 내부적으로 구조체를 사용하는 복합 유형 (ComplexType이 단지 래퍼 임)을 사용할 수도 있습니다.