2012-10-02 93 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

相关问题