2012-10-02 28 views
1

我是第一個實體框架代碼的品牌,所以任何幫助或方向將不勝感激。如何修改此實體框架代碼的第一個代碼?

目前,我有以下類:

public partial class Customer 
{ 
    public int Id { get; set; } 
    private ICollection<Address> _addresses; 
} 

public partial class Address 
{ 
    public int Id { get; set; } 
    public string Street { get; set; }; 
    public string City { get; set; }; 
    public string Zip { get; set; }; 
} 

及以下

public partial class CustomerMap : EntityTypeConfiguration<Customer> 
{ 
    public CustomerMap() 
    { 
     this.ToTable("Customer"); 
     this.HasKey(c => c.Id); 

     this.HasMany<Address>(c => c.Addresses) 
      .WithMany() 
      .Map(m => m.ToTable("CustomerAddresses")); 
    } 
} 

這個工程,我所期望的,並且爲該映射創建一個客戶,地址和CustomerAddresses表。現在對於我的問題..如果我需要修改代碼以生成以下內容,我該怎麼辦...

我想將CompanyCode屬性添加到「CustomerAddresses」表中......然後而不是構造一個地址集合..我想能夠構建一個散列表,其中的關鍵是CompanyCode,並且值是地址的集合。

所以,如果我有以下幾點:

Customer 
ID  C1 

Address 
ID  A1 
ID  A2 

CustomerAddresses 
CustomerID  C1 
AddressID  A1 
CompanyCode ABC 

CustomerID  C1 
AddressID  A2 
CompanyCode ABC 

CustomerID  C1 
AddressID  A2 
CompanyCode XYZ 

這樣的話,Customer.Addresses [ 「ABC」]將返回地址的集合與ID,A1和A2。而Customer.Addresses [「XYZ」]將返回ID爲A2的地址集合。

任何方向/幫助將不勝感激...謝謝。

回答

1

據我可以告訴它是不可能引入這樣一個導航屬性與索引器。您的索引器實際上是一個查詢,您必須將其表示爲查詢。我看到的唯一方法就是保持導航集合的原樣,並引入使用導航集合作爲過濾器的第二個(未映射)屬性。最大的缺點是這樣的過濾器會在LINQ到對象的內存中發生,並且需要在過濾集合之前始終首先從數據庫加載完整的集合(例如通過急切或惰性加載)。

我可能會將這樣一個過濾器從實體本身中刪除,並在存儲庫或服務類或通常從數據庫加載實體的位置/模塊中實現它。

您需要做的第一件事是將CustomerAddresses表作爲模型中的實體公開,因爲使用您的其他自定義屬性CompanyCode您不能再使用多對多關係,而需要兩個一對一多種關係。新的實體將是這樣的:

public partial class CustomerAddress 
{ 
    public int CustomerId { get; set; } 
    // public Customer Customer { get; set; } // optional 

    public int AddressId { get; set; } 
    public Address Address { get; set; } 

    public string CompanyCode { get; set; } 
} 

而且Customer需要被改爲:

public partial class Customer 
{ 
    public int Id { get; set; } 
    public ICollection<CustomerAddress> CustomerAddresses { get; set; } 
} 

您需要將映射更改爲:

public CustomerMap() 
{ 
    this.ToTable("Customer"); 
    this.HasKey(c => c.Id); 

    this.HasMany(c => c.CustomerAddresses) 
     .WithRequired() // or .WithRequired(ca => ca.Customer) 
     .HasForeignKey(ca => ca.CustomerId); 
} 

,並創建一個新的針對新實體的映射:

public CustomerAddressMap() 
{ 
    this.ToTable("CustomerAddresses"); 
    this.HasKey(ca => new { ca.CustomerId, ca.AddressId, ca.CompanyCode }); 
    // or what is the PK on that table? 
    // Maybe you need an Id property if this key isn't unique 

    this.HasRequired(ca => ca.Address) 
     .WithMany() 
     .HasForeignKey(ca => ca.AddressId); 
} 

現在,在一些服務類,你可以加載過濾地址:

public List<Address> GetAddresses(int customerId, string companyCode) 
{ 
    return context.CustomerAddresses.Where(ca => 
     ca.CustomerId == customerId && ca.CompanyCode == companyCode) 
     .ToList(); 
} 

或者,如果你想與過濾的地址一起加載客戶:

public Customer GetCustomer(int customerId, string companyCode) 
{ 
    var customer = context.Customer.SingleOrDefault(c => c.Id == customerId); 
    if (customer != null) 
     context.Entry(customer).Collection(c => c.CustomerAddresses).Query() 
      .Where(ca => ca.CompanyCode == companyCode) 
      .Load(); 
    return customer; 
} 

的最後一個例子是數據庫查詢。

在你可以使用投射的地址了CustomerAddresses收集的輔助屬性Customer實體:

public partial class Customer 
{ 
    public int Id { get; set; } 
    public ICollection<CustomerAddress> CustomerAddresses { get; set; } 

    public IEnumerable<Address> Addresses 
    { 
     get 
     { 
      if (CustomerAddresses != null) 
       return CustomerAddresses.Select(ca => ca.Address); 
      return null; 
     } 
    } 
} 

請記住,這個屬性不查詢數據庫,結果靠的是什麼已經加載到CustomerAddresses

+0

嘿,謝謝你的回覆..當你說它會加載完整的集合..你是說,一個特定的客戶的完整集合? – ntsue

+0

@ntsue:是的,確切的。 – Slauma

+0

好的,謝謝你,我會試試這個,讓你知道..我真的很感謝你把時間和細節放在你的答案中 – ntsue

相關問題