Database 我的实体模型设计错误,还是我做错了?
在我的Winform应用程序中,我有供应商、客户、运输公司。他们是相似的,因为他们基本上是某种类型的联系人,但是他们在可用字段方面略有不同 例如,供应商需要有StartDate和EndDate字段。目前,尽管供应商和客户可能有多个联系人\实体,但我们不会在这些版本中这样做,但运输公司将有多个联系人\实体和地址。同时,供应商和客户需要PO地址和交货地址,以及两个电话号码以防万一 目前,在我的代码优先实体中,我有供应商、客户和运输公司,每个公司都包含一个作为联系人类型的PrimaryContact,对于每个联系人类型,我都有一个地址和电话的ICCollection,该ICCollection依次存储一个或多个地址和电话信息。不同之处在于,运输公司除了PrimaryContact外,还将收集联系人 据我所知,即使我有自己设计DB/实体的自由,也不总是BLL中的对象正好映射下面的DB结构。 因此,我的想法是在我的BLL层,我将把数据从供应商翻译到BOSupplier,再翻译到表示层,当数据从表示层返回到DAL时,我将翻译到供应商。因为在我的演示层中,供应商看起来像:Database 我的实体模型设计错误,还是我做错了?,database,entity-framework-4.1,ef-code-first,Database,Entity Framework 4.1,Ef Code First,在我的Winform应用程序中,我有供应商、客户、运输公司。他们是相似的,因为他们基本上是某种类型的联系人,但是他们在可用字段方面略有不同 例如,供应商需要有StartDate和EndDate字段。目前,尽管供应商和客户可能有多个联系人\实体,但我们不会在这些版本中这样做,但运输公司将有多个联系人\实体和地址。同时,供应商和客户需要PO地址和交货地址,以及两个电话号码以防万一 目前,在我的代码优先实体中,我有供应商、客户和运输公司,每个公司都包含一个作为联系人类型的PrimaryContact,
public class BOSupplier
{
// Primery key
public int ID { get; set; }
public string Name { get; set; }
public string TaxNumber { get; set; }
public bool InActive { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string BankAccountNumber { get; set; }
public string BankAccountName { get; set; }
// Property related to Contact Table
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string SkypeName { get; set; }
// Proterty related to Address Table
// PO address Info
public string POAddressLine { get; set; }
public string POCity { get; set; }
public string PORegion { get; set; }
public string POCountry { get; set; }
public string POPostCode { get; set; }
// Delivery AddressLine
public string DelAddressLine { get; set; }
public string DelCity { get; set; }
public string DelRegion { get; set; }
public string DelCountry { get; set; }
public string DelPostCode { get; set; }
// Proterties related to Phone table
public string PhoneNumber1 { get; set; }
public string PhoneNumber2 { get; set; }
}
}
但在我的DAL层中,我的供应商将如下所示:
public class Supplier
{
// Primery key
public int ID { get; set; }
public string Name { get; set; }
public virtual Contact PrimaryContact { get; set; }
public string TaxNumber { get; set; }
public bool InActive { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string BankAccountNumber { get; set; }
public string BankAccountName { get; set; }
}
public static IEnumerable<BOSupplier> GetBOSuppliers()
{
var suppliers = dbContext.Suppliers;
BOSupplier currentSupplier;
foreach (Supplier supplier in suppliers)
{
currentSupplier = new BOSupplier()
{
ID = supplier.ID,
Name = supplier.Name,
Code = supplier.Code,
FirstName = supplier.PrimaryContact.FirstName,
TaxNumber = supplier.TaxNumber
};
// PO Address
Address poAddress = supplier.PrimaryContact.Addresses
.FirstOrDefault<Address>(a => a.AddressTypeValue == (int)AddressTypes.Postal);
if (poAddress != null)
{
currentSupplier.POAddressLine = poAddress.AddressLine1;
currentSupplier.POCity = poAddress.City;
currentSupplier.POCountry = poAddress.Country;
}
// Delivery Address
Address delAddress = supplier.PrimaryContact.Addresses
.FirstOrDefault<Address>(a => a.AddressTypeValue == (int)AddressTypes.Delivery);
if (delAddress != null)
{
currentSupplier.DelAddressLine = delAddress.AddressLine1;
currentSupplier.DelCity = delAddress.City;
currentSupplier.DelCountry = delAddress.Country;
}
// ToDo:
// There is probably more to think about how we want map multi phone numbers into limited two phone numbers
if (supplier.PrimaryContact.Phones.Count > 0)
{
foreach (Phone phone in supplier.PrimaryContact.Phones)
{
if (phone.PhoneType == PhoneTypes.Default)
{
currentSupplier.PhoneNumber1 = phone.PhoneNumber;
}
else
{
currentSupplier.PhoneNumber2 = phone.PhoneNumber;
}
}
}
this.boSupplierList.Add(currentSupplier);
}
return boSupplierList;
}
然后,当我为BLL类编写代码来管理我的中间BOSupplier对象和列表时,它实际上并没有将实体映射回DB端。似乎有很多低级代码只是为了从两个稍有不同的BOSupplier和Supplier传输/映射字段,如下所示:
public class Supplier
{
// Primery key
public int ID { get; set; }
public string Name { get; set; }
public virtual Contact PrimaryContact { get; set; }
public string TaxNumber { get; set; }
public bool InActive { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string BankAccountNumber { get; set; }
public string BankAccountName { get; set; }
}
public static IEnumerable<BOSupplier> GetBOSuppliers()
{
var suppliers = dbContext.Suppliers;
BOSupplier currentSupplier;
foreach (Supplier supplier in suppliers)
{
currentSupplier = new BOSupplier()
{
ID = supplier.ID,
Name = supplier.Name,
Code = supplier.Code,
FirstName = supplier.PrimaryContact.FirstName,
TaxNumber = supplier.TaxNumber
};
// PO Address
Address poAddress = supplier.PrimaryContact.Addresses
.FirstOrDefault<Address>(a => a.AddressTypeValue == (int)AddressTypes.Postal);
if (poAddress != null)
{
currentSupplier.POAddressLine = poAddress.AddressLine1;
currentSupplier.POCity = poAddress.City;
currentSupplier.POCountry = poAddress.Country;
}
// Delivery Address
Address delAddress = supplier.PrimaryContact.Addresses
.FirstOrDefault<Address>(a => a.AddressTypeValue == (int)AddressTypes.Delivery);
if (delAddress != null)
{
currentSupplier.DelAddressLine = delAddress.AddressLine1;
currentSupplier.DelCity = delAddress.City;
currentSupplier.DelCountry = delAddress.Country;
}
// ToDo:
// There is probably more to think about how we want map multi phone numbers into limited two phone numbers
if (supplier.PrimaryContact.Phones.Count > 0)
{
foreach (Phone phone in supplier.PrimaryContact.Phones)
{
if (phone.PhoneType == PhoneTypes.Default)
{
currentSupplier.PhoneNumber1 = phone.PhoneNumber;
}
else
{
currentSupplier.PhoneNumber2 = phone.PhoneNumber;
}
}
}
this.boSupplierList.Add(currentSupplier);
}
return boSupplierList;
}
我一直在想:也许我的实体模型应该更简单,或者有更好的方法来做我想做的事情?。因此,根据您的经验,请告诉我,我的实体模型过于复杂,或者我只需要一些更好的方法,从Bosupier映射到供应商或其他想法。根据您对领域的描述,您的实体模型并不复杂。您可以使用将供应商映射到BOSupplier。下面是一个使用AutoMapper展平对象图的示例 我发现你们的采购商有问题。当您访问PrimaryContact和地址时,它使用延迟加载。为了避免多次往返数据库,您可以按如下方式加载它们
var suppliers = dbContext.Suppliers.Include(s => s.PrimaryContact.Addresses);
谢谢你的评论。是的,我同意结构没有那么复杂。但我有点不确定我是否应该花时间编写这个低级映射代码,或者更好,使用映射器为我完成这项工作。但是,另一个选项不是尝试规范化联系人表,而是使用平面模型/表。我正在编写的应用程序是一个股票跟踪系统,它比灵活的联系人列表多得多。@pstar如果这种查询很常见,您可以对数据进行反规范化。另一个选择是使用micro ORM创建一个视图和查询。如果我想同时加载PrimaryContact和SecondaryContact,该怎么办?谢谢你,这确实很简单,我自己整理好了:D,谢谢你Eranga指出AutoMapper,我看了教程,看了视频后,非常有趣。我将为我们的供应商和客户稍微平坦表现在,并期待着使用汽车制造商的惊吓承运人。