1

假设我有一个简单的数据库示例,例如

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对象列表作为属性?或者更一般地说,我想,当联结表不仅包含两个表的主键的副本时,这是对多对多关系建模的正确方法吗?我最终会学习实体框架,但我想在学习时更接近金属。

4

3 回答 3

1

是的,构建ItemVisits类然后通过集合提供一对多关系是正确的方法。另一个令人感兴趣的项目是,您需要一种方法来在查询时返回和返回Visits。这当然是一种更具体的说法,即您需要一种从实体到实体的抽象方式。ItemsItemVisits

一种方法可能是延迟加载。因此,请考虑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.

另一种更老式的方法是在构造 的列表时传入Itemand对象。VisitItemVisit

最后,另一种更具可扩展性的方法是利用缓存和 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
}

真的没有什么不同。

于 2013-08-06T13:03:52.260 回答
0

在这样的表中添加多个主键会导致数据重复,这可能会导致问题:

  • 如果您必须更新项目的 ExpirationDate 会发生什么?

  • 如果您要修改访问(添加另一个项目)会发生什么?

此类主题的起点可能是:http ://en.wikipedia.org/wiki/Database_normalization#Normal_forms

编辑:我并不是说这通常是一个糟糕的解决方案,只是指出了额外的可能负担,尤其是在不使用 ORM 的情况下。欢迎反对者发表评论。

于 2013-08-06T13:01:19.730 回答
-1

oo 中的多对多关系是不同的。

访问有一个属性 ItemsVisits 项目也有一个属性 ItemsVisits

于 2013-08-06T13:03:17.460 回答