在没有 ORM 的情况下对多对多关系进行建模
本文关键字:关系 建模 情况下 ORM | 更新日期: 2023-09-27 18:26:33
假设我有一个简单的数据库示例,类似于
create table Items
(ItemId int
,ItemName varchar(50)
,ItemCost decimal
,ItemOrigin varchar(50) --maps to reference of country codes
,primary key (ItemId)
)
go
create table Visits
(VisitId int
,VisitDate datetime
,VisitLocation varchar(50) --maps to references of country codes
,primary key (VisitId)
)
go
create table ItemsVisits
(ItemId int
,VisitId int
,ItemsPurchased int
,ItemExpirationDate datetime
,TotalCost decimal --equals price * items purchased
,primary key(ItemId,VisitId)
)
public class Items
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public decimal ItemCost { get; set; }
public string ItemOrigin { get; set; }
}
public class Visits
{
public int VisitId { get; set; }
public DateTime VisitDate { get; set; }
public string VisitLocation { get; set; }
public List<Items> ItemsPurchased { get; set; }
}
上面的两个简单课程是我的第一个倾向。 在此示例中,Items
表是可以购买的内容的参考表,应用程序的"肉"位于Visits
表中。 使用上面的当前设置,我无法知道所购买物品的到期日期。(在这种情况下,假设某个 ItemId 随其到期日期而变化,具体取决于购买日期(。 我应该添加一个类似的类
public class ItemsVisits
{
public int ItemId { get; set; }
public int VisitId { get; set; }
public int ItemsPurchased { get; set; }
public DateTime ItemExpirationDate { get; set; }
public decimal TotalCost { get; set; }
}
然后使Visits
表具有ItemsVisits
对象列表作为属性? 或者更一般地说,我想,当连接表不仅仅包含两个表的主键副本时,这是对多对多关系进行建模的正确方法吗?我最终会学习实体框架,但我想在学习时更接近金属。
是的,构建ItemVisits
类,然后通过集合提供一对多关系是正确的方法。另一个感兴趣的项是,当您查询它时,您需要一种方法来返回Visits
并从ItemVisits
Items
。当然,这是一种更具体的方式,说你需要一种从实体到实体的抽象方式。
一种方法可能是延迟加载。因此,请考虑 ItemVisits
类上的几个新属性:
private Item _baseItem;
public Item BaseItem
{
get
{
if (_baseItem != null) { return _baseItem; }
// go get the item here and set the internal property
}
}
您需要这样做的原因很清楚。假设您正在查询ItemVisits
并且想要包含Item.ItemName
,那么您实际上无法这样做,因为您没有Item
。
另一种更老式的方法是在构造ItemVisit
列表时传入Item
和Visit
对象。
最后,另一种更具可扩展性的方法是利用缓存和 IoC。通过这种方式,您可以利用 ItemVisit
类的构造函数并通过 IoC 注入这些值。我不建议这样做,除非您有大量的事务负载并且有理由相信您将以荒谬的速度构建这些对象。当我说重要时,我说的是数百万笔交易。
编辑:对于多个主键:
如果我有一个只有两个主键的表:
public class LinkTable
{
// exists in the table
public int ItemId { get; set; }
private Item _refItem;
public Item RefItem
{
get
{
if (_refItem != null) { return _refItem; }
// go get the item
}
}
// exists in the table
public int VisitId { get; set; }
private Visit _refVisit;
public Visit RefVisit // sample impl as above
}
真的没有什么不同。
在此类表中添加多个主键会导致数据重复,这可能会导致问题:
-
如果您必须更新项目的到期日期,会发生什么情况?
-
如果您要修改访问(添加其他项目(会怎样?
该主题的起点可以是:http://en.wikipedia.org/wiki/Database_normalization#Normal_forms
编辑:我并不是说这是一个糟糕的解决方案,只是指出了额外的可能负担,尤其是在不使用ORM的情况下。欢迎反对者发表评论。
oo中的多对多关系是不同的。
访问有适当的项目访问项目也有适当的项目访问