我首先是Entity Framework代码的新手,所以我们非常感谢任何帮助或方向。
我目前有以下课程:
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"));
}
}
这正如我所料,并为映射创建Customer,Address和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的地址集合。
非常感谢任何方向/帮助......谢谢。
答案 0 :(得分:1)
据我所知,不可能用索引器引入这样的导航属性。您的索引器实际上是一个查询,您必须将其表达为查询。我看到的唯一方法是按原样保留导航集合,并引入第二个(未映射)属性,该属性使用过滤器的导航集合。最大的缺点是这样的过滤器会在LINQ-to-Objects的内存中发生,并且要求您在过滤集合之前首先从数据库中加载完整的集合(例如,通过急切或延迟加载)。
我可能会将这样的过滤器留在实体本身之外,并在存储库或服务类中实现它,或者通常是从数据库加载实体的地方/模块。
您需要做的第一件事是将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;
}
最后一个例子是两个数据库查询。
在Customer
实体中,您可以使用帮助属性来预测CustomerAddresses
集合中的地址:
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
的内容。