6

Tôi đã có yêu cầu sau đây hoạt động tốt trong không gian OO nhưng tôi không thể làm cho nó để bản đồ trở lại DB bằng cách sử dụng ADO EF mã đầu tiên.ADO EF Mã đầu tiên lớp trung gian kế thừa kế thừa

Tôi có các sản phẩm dạng số, mỗi sản phẩm sẽ có các khía cạnh khác nhau (thuộc tính nhưng không theo nghĩa thuộc tính mã). Ví dụ nhẫn sẽ có các khía cạnh như loại khoáng sản = vàng vv trong khi một viên kim cương sẽ có một aspec rõ ràng = VVSI1.

Như bạn có thể thấy các sản phẩm rất lớn trong thành phần của tôi và tôi muốn có một cách năng động để phát triển hệ thống của mình.

Như vậy tôi đã tạo ra một lớp sản phẩm:

public class Product 
{ 
    public int id { get; set; } 
    public string Name { get; set; } 
    private List<ProductAspect> aspects = new List<ProductAspect>(); 
    public List<ProductAspect> Aspects { get { return aspects; } set { aspects = value; } } 
} 

Nó có một danh sách các ProductAspect đó là lớp cơ sở cho tất cả các khía cạnh di chuyển về phía trước:

public class ProductAspect 
{ 
    public int id { get; set; } 
    public string AspectName { get; set; } 
} 

sau đó tôi thừa hưởng từ ProductAspect sử dụng một generic mà alows tôi để được cụ thể (mạnh mẽ gõ) về giá trị Aspect của tôi:

public abstract class ProductAspect<T> : ProductAspect 
{ 
    public T AspectValue { get; set; } 
} 

tôi sau đó tạo ra một số khía cạnh mà sẽ cho phép tôi để trang trí sản phẩm của tôi:

public class StringAspect : ProductAspect<string> { }; 
public class DecimalAspect : ProductAspect<decimal> { }; 
public class ImageAspect : ProductAspect<byte[]> { }; 

sau đó tôi cung cấp cho các DbContext thử và đã thử cả hai TPH và TPC ánh xạ thừa kế.

Dường như không hoạt động. Mô hình DB mà được tạo ra không tạo khóa cho các lớp StringAspect hoặc DecimalAspect từ Bảng Aspect.

public class IxamDataContext : DbContext 
{ 
    public DbSet<Product> Products { get; set; } 
    public DbSet<ProductAspect> Aspects { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     AspectMapping(modelBuilder); 
    } 

    private void AspectMapping(DbModelBuilder mb) 
    { 
     //TPH 
     //mb.Entity<ProductAspect>() 
     // .Map<StringAspect>(m => m.Requires("type").HasValue("sa")) 
     // .Map<DecimalAspect>(m => m.Requires("type").HasValue("da")); 

     //TPC 
     //mb.Entity<StringAspect>().ToTable("StringAspect"); 
     //mb.Entity<DecimalAspect>().ToTable("DecimalAspect"); 
    } 
} 

Hệ quả là các ngoại lệ sau đây cho mã Seeding này:

 Product p = new Product(); 
     p.Name = "Diamond"; 
     p.Aspects.Add(new StringAspect() { AspectName = "History", AspectValue = "Old and long" }); 
     p.Aspects.Add(new DecimalAspect() { AspectName = "Weight", AspectValue= 96.5M }); 


     context.Products.Add(p); 
     context.SaveChanges(); 

Excpetion:

EntityType 'StringAspect' không tồn tại trong 'IxamDataContext.Aspects' các EntitySet . Thông số tên: pháp nhân

Bất kỳ ý tưởng nào từ mã EF đầu tiên phát triển ở đó?

Trả lời

2

Khuôn khổ đối tượng không hỗ trợ các loại không được ánh xạ trung gian trong phân cấp thừa kế. Nó có nghĩa là bạn không thể có thừa kế này: A (ánh xạ) -> B (không được ánh xạ) -> C (ánh xạ). EF cũng không hỗ trợ ánh xạ các kiểu generic. Nó có nghĩa là bạn phải loại bỏ lớp trung gian chung của bạn khỏi hệ thống phân cấp và di chuyển AspectValue đến các kiểu có nguồn gốc với kiểu chính xác.

+0

Cảm ơn bạn đã trả lời. – Hugo

0

Có thể đã đến muộn, nhưng tôi sẽ cung cấp cho bạn sử dụng ComplexType attribute nó sẽ cho phép bạn mở rộng các loại của mình theo ý muốn.