使用Fluent NHibernate </string>将List <string>映射到分隔的字符串

时间:2010-11-17 19:40:01

标签: c# fluent-nhibernate

我的模型看起来像这样:

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

我希望我的数据库表是平的 - List应该存储为分隔的字符串: 功能一|功能二|功能三例如。

从数据库中检索时,应将每个项目放回List

这可能吗?

3 个答案:

答案 0 :(得分:11)

我在我当前的项目中做的一样,只是我将枚举的集合作为管道分隔的数字。它的工作方式相同。

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);
    }
}

答案 1 :(得分:0)

我为MySql set数据类型实现了类似的东西,它是db中逗号分隔的列表,但是实体模型中的字符串列表。它涉及在NHibernate中使用基于PrimitiveType类的自定义数据类型。你使用映射和.CustomType&lt;来连接它。地图上的CustomType&gt;()方法。

如果您愿意,我可以向您发送自定义类的代码snipet。

答案 2 :(得分:0)

我还为Point3D结构实现了类似的功能。正如cdmdotnet所说,你基本上想要实现和IUserType,它将通过NullSafeSet / NullSafeGet方法将功能打包/解包为单个字符串。

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

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

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

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

显然,标准的实现总是返回false。

应该如何解决这个问题?我不知道最佳做法是什么,但解决方案是:

  • 使IUserType.Equals(对象x,对象y)始终返回false。这将强制重建打包字符串,并且每次保存产品时都会进行数据库调用,无论Product是否已在语义上进行了更改。这是否是一个问题取决于任何因素(Feature对象的大小/数量,未更改时是否保存Product对象,您有多少Product对象等)。

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

  • 也许你可以重用NHibernate GenericListType类型的代码。当我实施上一个解决方案时,我没有足够的经验去做这件事。

如果您有NHibernate的一些经验,我希望这可以帮助您入门。如果不让我知道,我会尝试将更详细的解决方案放在一起。