代码之家  ›  专栏  ›  技术社区  ›  Alex

使用fluent nhibernate将list<string>映射为带分隔符的字符串

  •  7
  • Alex  · 技术社区  · 14 年前

    我的模型如下所示:

    public class Product
    {
        public string Name {get; set;}
        public string Description {get; set;}
        public double Price {get; set;}
        public List<string> Features {get; set;}
    }
    

    我希望数据库表是平面的-列表应存储为分隔字符串: 功能1功能2功能3例如。

    从数据库中检索时,它应该将这些项中的每一项放回列表中

    这有可能吗?

    3 回复  |  直到 14 年前
        1
  •  11
  •   DanB    14 年前

    我在当前的项目中也做了同样的工作,只是将一组枚举作为管道分隔的数字进行持久化。它的工作原理是一样的。

    public class Product
    {
        protected string _features; //this is where we'll store the pipe-delimited string
        public List<string> Features {
            get
            {
                if(string.IsNullOrEmpty(_features)
                    return new List<String>();
                return _features.Split(new[]{"|"}, StringSplitOptions.None).ToList();
            }
            set
            {
                _features = string.Join("|",value);
            }
        }
    }
    
    public class ProductMapping : ClassMap<Product>
    {
        protected ProductMapping()
        {
            Map(x => x.Features).CustomType(typeof(string)).Access.CamelCaseField(Prefix.Underscore);
        }
    }
    
        2
  •  0
  •   cdmdotnet    14 年前

    我为mysql set数据类型实现了类似的功能,它是数据库中逗号分隔的列表,但实体模型中的字符串列表。它涉及到在nhibernate中使用基于primitiveType类的自定义数据类型。您可以使用映射和映射上的.customType<customType>()方法将此连接到中。

    如果你愿意,我可以给你发送一个自定义类的代码截图。

        3
  •  0
  •   fostandy    14 年前

    我还为Point3D结构实现了类似的功能。正如cdmdotnet所说,您基本上想要实现和iuserType,它将通过nullsafeet/nullsafeget方法将特性打包/解包到单个字符串中。

    您可能还需要实现equals()方法,这有点微妙。最好用一个例子来说明原因:

        Product p = session.Load(...);
    p.Features.Add("extra feature");
    session.Save(p);
    

    问题是,水合作用下的NHIBERNATE存储了对P.Features的引用,并将其与保存请求时P.Features的值进行了比较。对于不可变的属性类型,这很好,但在上面的示例中,这些引用是相同的,因此有效的比较是

    var x = p.Features;
    var changed = Equals(x, x);
    

    显然,这一标准实现将始终返回false。

    一个人应该如何处理这个问题?我不知道最佳实践是什么,但解决方案是:

    • 使iusertype.equals(对象x,对象y)始终返回false。这将强制重新构建打包字符串,并在每次保存产品时进行数据库调用,而不管产品是否发生语义更改。这是否是一个问题取决于任何数量的因素(特性对象的大小/计数、未更改时是否保存产品对象、您拥有多少产品对象等)。

    • 使功能成为IList并实现 ChangeAwareList<T> : IList<T> 它能够跟踪更改(或保留其原始版本的副本)。实现iuserType.equals(对象x,对象y)以检查x/y是否为changeAwardList,并实现必要的逻辑以查看列表是否真的发生了更改。这就是我最终采用的解决方案。

    • 也许您可以重用NHibernate GenericListType类型的代码。在我实施之前的解决方案时,我没有足够的经验来尝试这个问题。

    如果你以前有过NHibernate的经验,我希望这能帮助你开始工作。如果不让我知道,我会尝试制定一个更详细的解决方案。