2012-08-14 22 views
8

Tôi có cấu trúc dữ liệu sau đây:Entity Framework nhiều người thuê chia sẻ kiến ​​trúc dữ liệu: Cột duy nhất, nhiều phím nước ngoài

//property Notification 
abstract class BindableBase { } 
//base class for all tenant-scoped objects 
abstract class TenantModelBase : BindableBase 
{ 
    int TenantId; 
} 

abstract class Order : TenantModelBase 
{ 
    Customer Customer; //works: mapped using TenantId and CustomerId 
    Product Product; //again, works with TenantId and ProductId 
    string ProductId; 
    string CustomerId; 
} 
class Customer: TenantModelBase 
{ 
    string CustomerId; 
} 

class Product : TenantModelBase 
{ 
    string ProductId; 
} 

class SpecialOrder : Order 
{ 
    OtherClass OtherClass; //this fails!, see below 
    string OtherClassId; 
} 
class SuperSpecialOrder : SpecialOrder { } 

class OtherClass : TenantModelBase 
{ 
    string OtherClassId; 
} 

tôi nhận được lỗi sau:

The foreign key component 'TenantId' is not a declared property on type 'SpecialOrder'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

Lỗi xảy ra bằng cách sử dụng cấu hình Api thạo :

 config.HasRequired(p => p.OtherClass) 
      .WithMany(oc => oc.SpecialOrders) 
      .HasForeignKey(p => new { p.TenantId, p.OtherClassId}); 

Nếu không có OtherClass tham chiếu trong SpecialOrder Tôi có thể tạo các đối tượng một cách tự do mà không gặp vấn đề gì (bao gồm SpecialOrder, SuperSpecialOrder v.v.).

Bất kỳ ai có manh mối gì đang xảy ra? Tôi đang bị mất ở đây :(

Sửa Tôi đã nhìn thấy trong các câu hỏi khác mà mọi người loại bỏ các TenantId từ các bảng, đây không phải là một lựa chọn từ khóa chính không phải là duy nhất trên toàn thuê nhà và chúng tôi muốn giữ lại chia sẻ kiến trúc dữ liệu.

tôi biết cách giải quyết là có một TenantId thứ hai trong lớp SpecialOrder, nhưng điều này dường như không hợp lý với tôi.

+0

Tôi nghĩ rằng đó là cùng một loại vấn đề như thế này: http: // stackoverflow.com/questions/10961690/inheritance-and-composite-foreign-keys-một phần-of-the-key-trong-cơ sở-lớp-các Bạn có thể hiển thị bản đồ của bạn chính xác hơn? 'Config' là gì? Tôi đoán một 'EntityTypeConfiguration ' với 'T' =' SpecialOrder', phải không? Ánh xạ trông như thế nào đối với 'Order.Customer'? Bạn có tạo bản đồ này với 'T' =' SpecialOrder' hoặc 'T' =' Order'? – Slauma

+0

Sự cố xảy ra khi tôi chỉ định ánh xạ cho cả Đơn đặt hàng và Đơn hàng đặc biệt. Sau đó nó sẽ mất đi bất kỳ tài sản nào được khai báo trong lớp cơ sở tại SpecialOrder. Nó có vẻ là cùng một câu hỏi. – Bas

Trả lời

7

bạn đang cố gắng để làm một TPT, nơi có một bảng riêng biệt cho thứ tự/Người thuê nhà? Nếu vậy, tôi nghĩ rằng áp phích khác là chính xác và có lỗi trong EF.

Nếu khách hàng/sản phẩm là các lớp được ánh xạ dựa trên của bạn, điều này có thể phù hợp với bạn.

Điều gì đã xảy ra với tôi khi tôi tạo cơ sở dữ liệu của bạn là nó đã cố gắng ánh xạ lớp Order trừu tượng.

Bằng cách thêm:

modelBuilder.Ignore<Order>(); 

Các builder giữ các thuộc tính ánh xạ do sự MapInheritedProperties, nhưng không tạo ra bảng để tất cả của FK được tạo ra một cách chính xác.

Tôi giả sử bạn muốn các bảng riêng biệt cho từng lớp học của bạn như bài đăng có liên quan ở trên và không ánh xạ bảng trừu tượng của bạn.

Toàn bộ mẫu:

public abstract class BindableBase { } 
    //base class for all tenant-scoped objects 
    public abstract class TenantModelBase : BindableBase 
    { 
     [Key] 
     public virtual int TenantId { get; set; } 
    } 

    public abstract class Order : TenantModelBase 
    { 
     public Customer Customer { get; set; } //works: mapped using TenantId and CustomerId 
     public Product Product { get; set; } //again, works with TenantId and ProductId 
     public string ProductId { get; set; } 
     public string CustomerId { get; set; } 
    } 
    public class Customer : TenantModelBase 
    { 
     [Key] 
     public string CustomerId { get; set; } 
    } 

    public class Product : TenantModelBase 
    { 
     [Key] 
     public string ProductId { get; set; } 
    } 

    public class SpecialOrder : Order 
    { 
     [Key] 
     public int SpecialOrderId { get; set; } 
     public OtherClass OtherClass { get; set; } //this fails!, see below 
     public string OtherClassId { get; set; } 
    } 
    public class SuperSpecialOrder : SpecialOrder { } 

    public class OtherClass : TenantModelBase 
    { 
     public string OtherClassId { get; set; } 
     public ICollection<SpecialOrder> SpecialOrders { get; set; } 
    } 



    public class Model : DbContext 
    { 
     public DbSet<Customer> Customers { get; set; } 
     public DbSet<Product> Products { get; set; } 
     public DbSet<SpecialOrder> SpecialOrders { get; set; } 
     public DbSet<SuperSpecialOrder> SuperSpecialOrders { get; set; } 

     public DbSet<OtherClass> OtherClasses { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
     modelBuilder.Entity<OtherClass>() 
      .HasKey(k => new { k.TenantId, k.OtherClassId }); 

     modelBuilder.Entity<Customer>() 
      .HasKey(k => new { k.TenantId, k.CustomerId }); 

     modelBuilder.Entity<Product>() 
      .HasKey(k => new { k.TenantId, k.ProductId }); 


     modelBuilder.Entity<SpecialOrder>() 
      .Map(m => 
        { 
         m.MapInheritedProperties(); 
         m.ToTable("SpecialOrders"); 
        }); 

     modelBuilder.Entity<SpecialOrder>().HasKey(k => new { k.TenantId, k.SpecialOrderId }); 

     modelBuilder.Entity<SuperSpecialOrder>() 
      .Map(m => 
      { 
      m.MapInheritedProperties(); 
      m.ToTable("SuperSpecialOrders"); 
      }) 
      .HasKey(k => new { k.TenantId, k.SpecialOrderId }); 

     modelBuilder.Entity<SpecialOrder>() 
      .HasRequired(p => p.OtherClass) 
      .WithMany(o => o.SpecialOrders) 
      .HasForeignKey(p => new { p.TenantId, p.OtherClassId }); 

     modelBuilder.Entity<Order>() 
      .HasRequired(o => o.Customer) 
      .WithMany() 
      .HasForeignKey(k => new { k.TenantId, k.CustomerId }); 

     modelBuilder.Entity<Order>() 
      .HasRequired(o => o.Product) 
      .WithMany() 
      .HasForeignKey(k => new { k.TenantId, k.ProductId }); 

     modelBuilder.Ignore<Order>(); 


     } 
    } 

Tạo Cơ sở dữ liệu: enter image description here

Hope this helps.

+0

+1: Phân tích thú vị! Tôi thấy rằng không lập bản đồ lớp 'Order' giải quyết vấn đề cụ thể trong câu hỏi, nhưng tôi tự hỏi nếu vấn đề không chỉ di chuyển một cấp trở lên hệ thống phân cấp thừa kế. Hãy tưởng tượng, 'SuperSpecialOrder' bây giờ là một tham chiếu đến' OtherClass'. Vì lớp cơ sở 'SpecialOrder' được ánh xạ ngay bây giờ, tôi đoán rằng ánh xạ FK tổng hợp trong' SuperSpecialOrder' sẽ ném cùng một ngoại lệ ngay bây giờ. Ngoài ra, là bản đồ TPC thay vì TPT cần thiết để có được điều này làm việc? – Slauma

+0

Điều này dường như là giải pháp duy nhất thực sự, chúng ta phải từ bỏ lập bản đồ TPH. Cảm ơn bạn vì câu trả lời tuyệt vời! – Bas

0

Tôi sẽ đoán tại đây khi tôi thấy một lỗi bất thường trong blog mà Julie Lermann đã làm với ef4.1 Không gian tên trong truy vấn gây ra sự cố.

Để nhanh chóng kiểm tra xem lỗi này có phải là vấn đề của bạn hay không, hãy thay đổi không gian tên của tất cả các đối tượng giống nhau. Không gian tên xyz // giống như dbcontext và và các đối tượng lớp công khai OtherClass {}

Kiểm tra nhanh. Nếu không, xin lỗi vì đã lãng phí thời gian của bạn.

+0

Xin chào soadyp, cảm ơn bạn đã nhập liệu, nhưng tất cả các lớp đều ở cùng một không gian tên! – Bas

Các vấn đề liên quan