【问题标题】:NHibernate mapping with no empty constructor and no settersNHibernate 映射没有空的构造函数和设置器
【发布时间】:2010-06-08 15:12:05
【问题描述】:

我正在测试将 NHibernate 与一个完全不了解它并且不打算适应任何限制的域一起使用是多么困难。

在我在网络上发现的许多示例中,被映射的域是贫血域的又一个示例,其中对象与简单的数据持有者相差不远。当然,这使得映射变得简单,而且它可能会吸引以数据为中心的人/情况,但我不喜欢听到我脑海中的声音说“C 也有结构,你知道吗?”,“类不是只是花哨的命名空间,你知道吗?”,或者“你为什么不使用 CREATE TABLE 来代替?”。

但回到 NHibernate。 NHibernate 迫使我将属性设为虚拟,以便能够代理它们以进行延迟加载。这是我不介意的,因为我可能也需要它们作为一些 AOP 东西的虚拟。 我不满意的限制是需要一个空的构造函数和需要设置器/属性。我希望我的实体以有效状态创建,并且大多数时候这意味着没有空的构造函数。 出于通常的原因,我也不想公开集合属性的设置器。哦,还有不应该直接更改的属性的设置器。

在某处的领域模型中考虑这种简化和人为的聚合:

public class ShoppingCartItem
{
    private readonly Product product;

    public ShoppingCartItem(Product product, int quantity)
    {
        if(quantity <= 0)
            throw new ArgumentOutOfRangeException("quantity");
        this.product = product;
        this.quantity = quantity;
    }
    public virtual Product Product
    {
        get { return product; }
    }
    private int quantity;
    public virtual int Quantity
    {
        get { return quantity; }
        set
        {
            if(value <= 0)
                throw new ArgumentOutOfRangeException("value");
            quantity = value;
    }

    public virtual Money TotalPrice
    {
        get { return product.Price * quantity; }
    }
}

public class ShoppingCart : Entity
{
    private readonly IDictionary<Product, ShoppingCartItem> items =
        new Dictionary<Product, ShoppingCartItem>();
    private readonly ISet<DiscountCoupon> discountCoupons =
        new HashSet<DiscountCoupon>();

    public virtual IEnumerable<ShoppingCartItem> Items
    {
        get { return items.Values; }
    }

    public virtual IEnumerable<DiscountCoupon> DiscountCoupons
    {
        get { return discountCoupons; }
    }

    public virtual void AddProduct(Product product)
    {
        ShoppingCartItem item;
        if(items.TryGetValue(product, out item))
            item.Quantity++;
        else
            items.Add(product, new ShoppingCartItem(product, 1));
    }

    public virtual void RemoveProduct(Product product)
    {
        ShoppingCartItem item;
        if(!items.TryGetValue(product, out item))
            throw new ArgumentException("product");

        if(item.Quantity == 1)
            items.Remove(product);
        else
            item.Quantity--;
    }

    public virtual int AddDiscountCoupon(DiscountCoupon coupon)
    {
        discountCoupons.Add(coupon);
    }

    public virtual int RemoveDiscountCoupon(DiscountCoupon coupon)
    {
        discountCoupons.Remove(coupon);
    }

    public virtual Money CalculatePrice()
    {
        // Missing complex discount logic
        return items.Values.Sum(item => item.TotalPrice);
    }
}

大多数属性没有设置器,也没有空的构造函数。集合不是直接干预的,而是通过专门的方法干预的。我可以利用 NHibernate 的可扩展性来映射它吗?还是我想再次敲一个螺丝?还是两者兼有?

【问题讨论】:

    标签: nhibernate orm nhibernate-mapping mapping


    【解决方案1】:

    你可以将私有/内部/受保护的设置器放在属性/集合上,nhibernate 会正确加载它们(第 4.1.1 章)

    构造函数必须在那里,但您没有义务将其设为公共构造函数(第 4.1.2 章)

    来自最新http://sourceforge.net/projects/nhibernate/files/NHibernate/2.1.2GA/NHibernate-2.1.2.GA-reference.zip/download的章节参考

    【讨论】:

      【解决方案2】:

      首先,您可以将空构造函数设为私有,以便其他人无法访问它。 NH 仍然可以到达。

      第二次关闭 NH 可以随心所欲地访问您的房产。

      access="backfield" 用于公共虚拟产品 Product { get;私人套装; }

      access="field.pascalcase-m-underscore" 用于 m_Product

      access="field.pascalcase-underscore" for _Product

      还有其他访问策略,我敢肯定您甚至可以根据需要创建自己的访问策略。

      【讨论】:

      • 其实访问策略并不总是需要明确定义
      • 这不太正确。构造函数应该受到保护。来自异常:“NHibernate.InvalidProxyTypeException:以下类型不能用作代理:ClassA:类型应该有一个可见的(公共或受保护的)无参数构造函数”。文档(4.1.2)说:“类必须有一个默认构造函数(可能是非公共的)”
      猜你喜欢
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2011-12-29
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多