如何映射 IDictionary在流利的 NHibernate 中?

发布于 2024-08-25 12:59:53 字数 1474 浏览 9 评论 0原文

我希望将用户首选项保留到名称值对的集合中,其中值可以是 int、bool 或 string。

有几种方法可以给这只猫剥皮,但我能想到的最方便的方法是这样的:

public class User
{
    public virtual IDictionary<string, object> Preferences { get; set; }
}

其用法如下:

user.Preferences["preference1"] = "some value";
user.Preferences["preference2"] = 10;
user.Preferences["preference3"] = true;

var pref = (int)user.Preferences["preference2"];

我不确定如何在 Fluent NHibernate 中映射它,尽管我确实认为这是可能的。

一般来说,您会映射一个更简单的 Dictionaryas:

HasMany(x => x.Preferences)
    .Table("Preferences")
    .AsMap("preferenceName")
    .Element("preferenceValue");

但是对于“对象”类型,NHibernate 不知道如何处理它。我想象可以创建一个自定义 UserType,将“对象”分解为表示其类型的字符串和表示值的字符串。我们会有一个看起来像这样的表:

Table Preferences
    userId (int)
    preferenceName (varchar)
    preferenceValue (varchar)
    preferenceValueType (varchar)

hibernate 映射会像这样:

<map name="Preferences" table="Preferences"> 
  <key column="userId"></key> 
  <index column="preferenceName" type="String" />
  <element type="ObjectAsStringUserType, Assembly">
    <column name="preferenceValue" /> 
    <column name="preferenceValueType"/> 
  </element> 
</map> 

我不确定如何在 Fluent NHibernate 中映射它。

也许有更好的方法来做到这一点,或者也许我应该忍住并使用 IDictionary。有什么想法吗?

I am looking to persist user preferences into a collection of name value pairs, where the value may be an int, bool, or string.

There are a few ways to skin this cat, but the most convenient method I can think of is something like this:

public class User
{
    public virtual IDictionary<string, object> Preferences { get; set; }
}

with its usage as:

user.Preferences["preference1"] = "some value";
user.Preferences["preference2"] = 10;
user.Preferences["preference3"] = true;

var pref = (int)user.Preferences["preference2"];

I'm not sure how to map this in Fluent NHibernate, though I do think it is possible.

Generally, you would map a simpler Dictionary<string, string> as:

HasMany(x => x.Preferences)
    .Table("Preferences")
    .AsMap("preferenceName")
    .Element("preferenceValue");

But with a type of 'object', NHibernate doesn't know how to deal with it. I imagine a custom UserType could be created that breaks an 'object' down to a string representing its Type and a string representing the value. We would have a table that looks kind of like this:

Table Preferences
    userId (int)
    preferenceName (varchar)
    preferenceValue (varchar)
    preferenceValueType (varchar)

and the hibernate mapping would like this:

<map name="Preferences" table="Preferences"> 
  <key column="userId"></key> 
  <index column="preferenceName" type="String" />
  <element type="ObjectAsStringUserType, Assembly">
    <column name="preferenceValue" /> 
    <column name="preferenceValueType"/> 
  </element> 
</map> 

I'm not sure how you would map this in Fluent NHibernate.

Maybe there's a better way to do this, or maybe I should just suck it up and use IDictionary<string, string>. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挽袖吟 2024-09-01 12:59:53

我想说 IDictionary 会容易得多。然而这是代码

        HasMany(u => u.Preferences)
            .Table("Preferences")
            .AsMap("preferenceName")
            .Element("preferenceType", e => e.Column("preferenceValue").Type<ObjAsStringUserType>());

class ObjAsStringUserType : ImmutableUserType
{
    public override object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var type = (string)NHibernateUtil.String.NullSafeGet(rs, names[0]);
        var value = (string)NHibernateUtil.String.NullSafeGet(rs, names[1]);

        switch (type)
        {
            case "boolean":
                return bool.Parse(value);
                ...
            default:
                return null;
                break;
        }
    }

    public override void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var type = value.GetType().Name;
        var valuestring = value.ToString(CultureInfo.InvariantCulture);

        NHibernateUtil.String.NullSafeSet(cmd, type, index);
        NHibernateUtil.String.NullSafeSet(cmd, valuestring, index + 1);
    }

    public override Type ReturnedType
    {
        get { return typeof(object); }
    }

    public override SqlType[] SqlTypes
    {
        get { return new []
        {
            SqlTypeFactory.GetString(length: 255),  // preferenceType
            SqlTypeFactory.GetString(length: 255),  // preferenceValue
        };
        }
    }
}

i would say IDictionary<string,string> would be a lot easier. However here's the code

        HasMany(u => u.Preferences)
            .Table("Preferences")
            .AsMap("preferenceName")
            .Element("preferenceType", e => e.Column("preferenceValue").Type<ObjAsStringUserType>());

class ObjAsStringUserType : ImmutableUserType
{
    public override object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var type = (string)NHibernateUtil.String.NullSafeGet(rs, names[0]);
        var value = (string)NHibernateUtil.String.NullSafeGet(rs, names[1]);

        switch (type)
        {
            case "boolean":
                return bool.Parse(value);
                ...
            default:
                return null;
                break;
        }
    }

    public override void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var type = value.GetType().Name;
        var valuestring = value.ToString(CultureInfo.InvariantCulture);

        NHibernateUtil.String.NullSafeSet(cmd, type, index);
        NHibernateUtil.String.NullSafeSet(cmd, valuestring, index + 1);
    }

    public override Type ReturnedType
    {
        get { return typeof(object); }
    }

    public override SqlType[] SqlTypes
    {
        get { return new []
        {
            SqlTypeFactory.GetString(length: 255),  // preferenceType
            SqlTypeFactory.GetString(length: 255),  // preferenceValue
        };
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文