【问题标题】:Mapping a custom type property in Fluent NHibernate在 Fluent NHibernate 中映射自定义类型属性
【发布时间】:2016-08-02 09:30:38
【问题描述】:

我有一个数据库,它保存了一个项目的Id,该项目存储在另一个系统中并反序列化为代码中的一个对象。我正在尝试使用 Fluent NHibernate 构建一个由数据库和外部服务中的数据组成的域模型实体。一个例子将更好地解释这一点。在数据库中,我有一个如下所示的表:

CREATE TABLE entities
(
  id integer NOT NULL,
  custom_thing text NOT NULL,
  CONSTRAINT entities_id_pk PRIMARY KEY (id)
);

它是 PostgreSQL,但问题不是特定于数据库的。现在在代码中我有这些类:

class Entity
{
    public virtual int Id { get; set; }

    public virtual CustomThing CustomThing { get; set; }
}

class CustomThing
{
    public string Id { get; set; }
    public string Name { get; set; }
}

我正在尝试使用CustomMap 来定义映射:

class EntityMap : ClassMap<Entity>
{
    public EntityMap()
    {
        Table("entities");
        Id(e => e.Id, "id").GeneratedBy.Assigned();
        // Map(e => e.CustomThing, "custom_thing");
    }
}

问题是:如何映射 CustomThing?这是一个尝试映射实体类的程序(如果针对 PostgreSQL 数据库运行,则需要 FluentNHibernate 包和 NpgSQL)。为简单起见,我只是在代码中创建 CustomThing 的实例:

class Program
{
    // How to use this in mapping?
    static CustomThing[] _customThings =
    {
        new CustomThing {Id = "abc", Name = "ABC"},
        new CustomThing {Id = "def", Name = "DEF"}
    };

    static void Main()
    {
        using (ISessionFactory sessionFactory = Fluently.Configure()
            .Database(PostgreSQLConfiguration.Standard
                .ConnectionString(
                    @"Server=localhost; Database=test_nhibernate; User Id=postgres; Password=little_secret;"))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Entity>())
            .BuildSessionFactory())
        {
            using (ISession session = sessionFactory.OpenSession())
            {
                var entity = session.Get<Entity>(1);

                Console.WriteLine($"{entity?.Id} {entity?.CustomThing?.Name}");
            }
        }
        Console.ReadLine();
    }
}

输出当然只是 Id 属性值,因为未定义 CustomThing 的映射。是否可以配置映射,以便我可以将参数传递给它并以某种方式通过 Id 属性将 custom_thing 列值映射到 _customThings 中的对象?

【问题讨论】:

  • 我解决了同样的问题,将这个属性存储为 json 文本并创建新的自定义 'UserType' 来序列化和反序列化对象,如果这个解决方案适合你,我可以为你提供一些代码 sn- ps?
  • @mdameer 谢谢,好的,我想我明白了这一点,但是您是如何指示映射器分配该 JSON 的呢?我假设您的意思是 Entity.CustomThing 在这里是 string 类型。问题是在entities 表中我不存储整个序列化CustomThing,而只存储它的Id。其他属性来自外部服务,它具有完整的CustomThing JSON 结构。您的解决方案在这种情况下是否有效?

标签: c# nhibernate fluent-nhibernate fluent-nhibernate-mapping


【解决方案1】:

是的,您可以通过保存Id 并在代码中获取其余数据,或者将所有内容放入映射器中以将对象返回给您,如果您选择第二个选项,则可以按照此操作代码:

[Serializable]
public class CustomThingUserType : IUserType {
    public new bool Equals(object x, object y) {
        if (object.ReferenceEquals(x, y))
            return true;

        if (x == null || y == null)
            return false;

        return x.Equals(y);
    }

    public int GetHashCode(object x) {
        if (x == null)
            return 0;

        return x.GetHashCode();
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner) {
        if (names.Length == 0)
            throw new ArgumentException("Expecting at least one column");

        int id = (int)NHibernateUtil.Int32.NullSafeGet(rs, names[0]);

        var obj = new CustomThing { Id = id };

        // here you can grab your data from external service

        return obj;
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index) {
        var parameter = (DbParameter)cmd.Parameters[index];

        if (value == null) {
            parameter.Value = 0;
        }
        else {
            parameter.Value = ((CustomThing)value).Id;
        }
    }

    public object DeepCopy(object value) {
        return value;
    }

    public object Replace(object original, object target, object owner) {
        return original;
    }

    public object Assemble(object cached, object owner) {
        return cached;
    }

    public object Disassemble(object value) {
        return value;
    }

    public SqlType[] SqlTypes {
        get {
            return new SqlType[] { new SqlType(DbType.Int32) };
        }
    }

    public Type ReturnedType {
        get { return typeof(CustomThing); }
    }

    public bool IsMutable {
        get { return false; }
    }
}

【讨论】:

  • 第二个选项确实有效。为了完整起见,我将添加 EntityMap 中的映射现在应该如下所示:Map(e =&gt; e.CustomThing, "custom_thing").CustomType&lt;CustomThingUserType&gt;();。我还必须将id 类型更改为字符串以适合我的示例。谢谢! :)
猜你喜欢
  • 1970-01-01
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 2014-12-09
  • 2011-03-02
  • 1970-01-01
  • 2018-03-22
相关资源
最近更新 更多