4

Entity Framework 4でプロパティがサポートされていないことに出くわしたのでenum、回避策を説明する次の記事を見つけました。

Entity Framework 4.0 Beta 1 – POCO Enum サポート?

OrderStatusWrapperデザイナではなくコードで (記事で説明されているように)へのデータベース列のマッピングを表現するにはどうすればよいですか?

アップデート:

提供された回答に基づいて、OrderStatus列挙OrderStatusWrapper型を型に置き換える必要があることに気づきませんでした。

それ以外の:

public class Order 
{
    public OrderStatus Status { get; set; }
}

私は使用する必要があります:

public class Order 
{
    public OrderStatusWrapper Status { get; set; }
}

ただし、次のコードを実行すると、次のようになります。

// OrderContext class defined elsewhere as:
// public class OrderContext : DbContext
// {
//   public DbSet<Order> Orders { get; set; }
// }
using(OrderContext ctx = new OrderContext())
{
    Order order = new Order { Status = OrderStatus.Created; }
    ctx.Orders.Add(order);
    ctx.SaveChanges();
} 

次の例外が発生します (簡潔にするためにトリミングされています)。

System.Data.SqlClient.SqlException
            Message=列名「値」が無効です。

データベース列の名前はStatusです。Statusプロパティを次のように装飾してみました:

[Column("Status")]

それから

[Column("Status"), TypeName("OrderStatus")]

[Column("Status"), TypeName("OrderStatusWrapper")]

しかし、これはこの例外を解決しません。

Columnまた、属性を削除してこれを実行しようとしました:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>()
      .Property(p => p.OrderStatus)
      .HasColumnName("OrderStatus");
}

しかし、次のコンパイル エラーが発生します。

エラー 1 型 'ConsoleApplication1.OrderStatusWrapper' は、ジェネリック型またはメソッド 'System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.Property( System.Linq.Expressions.Expression>)' [切り取ったパス]

4

2 に答える 2

3

次のコードは、Code First CTP5 でマッピングがどのように見えるかを示しています。この場合、Code First は、 Reachability Conventionに基づいて機能するComplex Type DiscoveryOrderStatusWrapperと呼ばれる概念により、自動的に複合型として認識されます。または流暢な API を使用して、OrderStatusWrapper を複合型として明示的に登録する必要さえありません。ComplexTypeAttributeComplexType<T>()

詳細については、この投稿をご覧ください:
Code First CTP5 を使用したエンティティ関連付けマッピング: 複合型

アップデート:

CTP5 のバグにより、複雑なタイプのプロパティ (DB の OrderStatusWrapper.Value の [Orders].[Status] など) にカスタムの列名が必要な場合は、次のように明示的にマークする必要があります[ComplexType]

public class Order
{
    public int OrderId { get; set; }
    public DateTime CreatedOn { get; set; }               
    public OrderStatusWrapper Status { get; set; }
}    

[ComplexType]
public class OrderStatusWrapper 
{
    private OrderStatus _status;

    [Column(Name="Status")]
    public int Value {
        get { return (int)_status; }
        set { _status = (OrderStatus)value; }
    }
    public OrderStatus EnumValue {
        get { return _status; }
        set { _status = value; }
    }
}

public enum OrderStatus
{
    OrderCreated,
    OrderPayed,
    OrderShipped
}

既存のデータベースで作業しているため、オプションでデータベースのメタデータ テーブルをオフにすることもできます。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Conventions
                .Remove<System.Data.Entity.Database.IncludeMetadataConvention>();
}
于 2010-12-19T19:03:47.020 に答える
3

コンテキスト ファイルに次のように記述します。

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ComplexType<OrderStatusWrapper>();
            base.OnModelCreating(modelBuilder);
        }

それはうまくいくはずです。

編集:

public class Order
{
     public...
     ...
     public OrderStatusWrapper OrderStatus { get; set; }
}

public ActionResult Index()
{
    var result = _context.Orders.Where(o => o.OrderStatus == OrderStatus.ReadyForShipping);

    _context.Orders.Add(new Order{ ..., OrderStatus = OrderStatus.Shipped });

    ...;
}

その例が示すように、私が上記に示した小さなコード片と一緒に行った場合(EDIT :)までは、期待どおりに動作するはずです。

EDIT nr2: ラッパーが次のようになっている場合:

public class OrderStatusWrapper
{
    private OrderStatus _status;

    public int Value
    {
        get { return (int)_status; }
        set { _status = (OrderStatus)value; }
    }
    public OrderStatus EnumValue
    {
        get { return _status; }
        set { _status = value; }
    }
    public static implicit operator
         OrderStatusWrapper(OrderStatus status)
    {
        return new OrderStatusWrapper { EnumValue = status };
    }

    public static implicit operator
        OrderStatus(OrderStatusWrapper statusWrapper)
   {
       if (statusWrapper == null) return OrderStatus.OrderCreated;
       else return statusWrapper.EnumValue;
   }
}

データベースはプロパティ値の名前を取得するため、そのプロパティ名をステータスに変更すると、データベースの列はステータスに変更されます。

于 2010-12-19T18:34:27.787 に答える