Nhibernate映射:在对象中封装列表

Nhibernate映射:在对象中封装列表,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,我有两个表Deal和Cost。成本可以有多种类型,如计划内、计划外。每笔交易都可能有一笔——每种类型的成本只有一笔。这很容易映射为多对一的交易,并在成本上重新组合。但是我想要的是创建一个costs对象,它为每个cost都命名了属性。因此,对于如下所示的数据库: Deal: Cost ID Name ID DealID Type Value --------- ----------------------

我有两个表
Deal
Cost
。成本可以有多种类型,如计划内、计划外。每笔交易都可能有一笔——每种类型的成本只有一笔。这很容易映射为多对一的交易,并在成本上重新组合。但是我想要的是创建一个costs对象,它为每个cost都命名了属性。因此,对于如下所示的数据库:

Deal:               Cost
ID   Name           ID   DealID   Type        Value
---------           -------------------------------
1    Test           1    1        Planned     10
                    2    1        Unplanned   5
public class Deal
{
    private IList<Cost> _costs = new List<Cost>(2); // map this collection

    public Cost PlannedCost
    {
        get { return _costs.FirstOrDefault(c => c.Type == CostType.Planned); }
        set
        {
            var plannedCost = _costs.FirstOrDefault(c => c.Type == CostType.Planned);
            if (plannedCost != null)
            {
                _costs.Remove(plannedCost);
            }
            _costs.Add(value);
        }
    }

    public Cost UnplannedCost { // similarly }
}
像这样容易接近

Deal.Costs.Planned = 10m;
Deal.Costs.Unplanned = 5m;
如何绘制此图是最好的方法?我甚至应该映射它,还是应该手工编写属性来查询底层集合


我看到的困难是映射cost的属性,以便它们映射到同一个表中的不同行。使用其中一列作为鉴别器。

这听起来并不像成本是一个列表

我会将成本映射为交易中的财产。如果要保留Deal.Costs.Planned语法,可以使用组件映射。

手工编写属性方法:

public class Deal
{
    public virtual Cost GetPlannedCost() 
    {
        return _costs.FirstOrDefault(x => x.IsPlanned()); 
    }

    public virtual Cost GetUnplannedCost() {}
    {
        return _costs.FirstOrDefault(x => x.IsUnplanned()); 
    }

    public virtual Cost[] GetAllCosts() 
    {
        return _costs.ToArray(); 
    }

    private ISet<Cost> _costs = new HashedSet<Cost>();
}
公共类交易
{
公共虚拟成本GetPlannedCost()
{
返回_costs.FirstOrDefault(x=>x.IsPlanned());
}
公共虚拟成本GetUnPlanedCost(){}
{
返回_costs.FirstOrDefault(x=>x.IsUnplanned());
}
公共虚拟成本[]GetAllCosts()
{
返回_costs.ToArray();
}
私有ISet_costs=new HashedSet();
}

我会将成本映射为私人收集,并公开交易中的计划内和计划外成本。这将允许您将“每笔交易都可能有一笔——每种类型的成本中只有一笔”作为业务规则。它看起来像这样:

Deal:               Cost
ID   Name           ID   DealID   Type        Value
---------           -------------------------------
1    Test           1    1        Planned     10
                    2    1        Unplanned   5
public class Deal
{
    private IList<Cost> _costs = new List<Cost>(2); // map this collection

    public Cost PlannedCost
    {
        get { return _costs.FirstOrDefault(c => c.Type == CostType.Planned); }
        set
        {
            var plannedCost = _costs.FirstOrDefault(c => c.Type == CostType.Planned);
            if (plannedCost != null)
            {
                _costs.Remove(plannedCost);
            }
            _costs.Add(value);
        }
    }

    public Cost UnplannedCost { // similarly }
}
公共类交易
{
私有IList _costs=new List(2);//映射此集合
公共成本计划成本
{
获取{返回_costs.FirstOrDefault(c=>c.Type==CostType.Planned);}
设置
{
var plannedCost=_costs.FirstOrDefault(c=>c.Type==CostType.Planed);
if(plannedCost!=null)
{
_成本。移除(计划成本);
}
_成本。增加(价值);
}
}
公共成本计划外成本{//0}
}

您可以使用NHibernate映射的formula标记在类中拥有公式属性。公式只是一条SQL语句,将作为子查询插入映射查询中。 显然,公式属性是只读的,无法更新

由于您希望为每笔交易计算这些属性,因此应将它们添加为交易属性(如果您希望使用公式),因此您将拥有:

Deal.UnPlannedCosts
Deal.PlannedCosts

这是一篇解释公式属性的文章。

这很有意义。但如何让组件映射从列表的每个属性的成本表中选择不同的行,我需要设置某种类型的鉴别器,我想,但我从未见过这样做。如果将成本映射为交易属性,则需要向交易表添加外键。我假设你当然可以控制数据库,数据库已经有了这种结构。困难在于将属性映射到同一表的不同行。这个问题已经被编辑过了,以便更清楚。嗯,据我所知,并没有办法映射这个问题。我认为你最好的选择是采取马特建议的方法。您可以将收藏设置为私人收藏,这样人们就无法从收藏中手动添加/删除项目。然后,您的属性将需要包含一些逻辑,以使内部集合保持最新。因此,当您设置一个值时,它会将该项目添加到集合中。这不允许我使用deal.costs.CostName的符号。对我来说,这是映射中有问题的部分。