如何用NHibernate正确定义值对象?

时间:2013-01-28 12:47:40

标签: nhibernate fluent-nhibernate

我想通过组件查询NHibernate Linq。该组件包含覆盖等于中的未包含的Date属性。我只想在要求相等时跳过Date属性。目前 Date属性在Address类的ctor中设置,因此查询将返回 0行。我知道这打破了Value Object概念,但我只是想知道为什么下面的代码无法正常工作。

QUERY 正如您所见,Date属性位于查询中

select user0_.Id     as Id0_,
       user0_.Name   as Name0_,
       user0_.Number as Number0_,
       user0_.Date   as Date0_
from   test1 user0_
where  (user0_.Number = 1 /* @p0 */
        and user0_.Date = '2013-01-28T14:29:47.00' /* @p1 */)

主要

class Program
    {
        private static ISessionFactory _sessionFactory;

        private static void CreateSessionFactory()
        {
            FluentConfiguration config = Fluently
                .Configure(new Configuration().Configure())
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>());
            new SchemaExport(config.BuildConfiguration()).Create(false, true);
            _sessionFactory = config.BuildSessionFactory();
        }

        [STAThread]
        static void Main(string[] args)
        {
            CreateSessionFactory();

            using (var session = _sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var user = new User()
                {
                    Name = "Nik",
                    Address = new Address(1)
                };
                session.Save(user);
                tx.Commit();
            }

            using (var session = _sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                session.Query<User>().Where(x => x.Address == new Address(1)).Single();
                tx.Commit();
            }
        }
    }

课程和地图

public class Address : IEquatable<Address>, IEqualityComparer<Address>
    {
        protected Address() { }

        public Address(int number)
        {
            Number = number;
            Date = DateTime.Now;
        }

        public virtual int Number { get; protected set; }
        public virtual DateTime Date { get; protected set; }

        public override bool Equals(object obj)
        {
            return Number == ((Address)obj).Number;
        }

        public override int GetHashCode()
        {
            return Number.GetHashCode();
        }

        public bool Equals(Address other)
        {
            return Number == other.Number;
        }

        public bool Equals(Address x, Address y)
        {
            return x.Number == y.Number;
        }

        public int GetHashCode(Address obj)
        {
            return obj.GetHashCode();
        }
    }

    public class User
    {
        public virtual Guid Id { get; set; }
        public virtual string Name { get; set; }
        public virtual Address Address { get; set; }
    }

    public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Table("test1");
            Id(x => x.Id).GeneratedBy.GuidNative();
            Map(x => x.Name);
            Component(x => x.Address, cm =>
            {
                cm.Map(x => x.Number);
                cm.Map(x => x.Date);
            });
        }
    }

1 个答案:

答案 0 :(得分:1)

您已将地址映射为组件。因此,当您要求NHibernate将user.Address与某个Address实例进行比较时,它将比较每个属性。 NHibernate不分析编译代码以确定在Equals()方法中使用哪些属性。

代码正常运行。

您可以编写查询以分别比较每个属性,而不是比较整个地址。或者尝试重新考虑设计,使地址成为真正的价值对象。