Nhibernate在父对象

时间:2016-01-21 21:52:46

标签: nhibernate nhibernate-mapping mapping-by-code

假设我有以下模型

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

public class ActivityLog
{
    public virtual Guid Id { get; set; }
    public virtual Guid CustomerId { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual DateTime ActivityDate { get; set; }
}

我希望能够通过调用

删除客户和所有相应的ActivityLog项目
 session.Delete(customer);

我不想要的是拥有房产     我的Customer类中的List<ActivityLog> Logs。是否有可能在Nhibernate中实现?我已经尝试过EF,它可以在那里工作,但是在HN中获得了引用约束异常。

我的映射:

public class CustomerMap : ClassMapping<Customer>
{
    public CustomerMap()
    {
        Id(x => x.Id, map => map.Generator(Generators.GuidComb));
        Property(x => x.Name);

    }
}

public class ActivityLogMap : ClassMapping<ActivityLog>
{
    public ActivityLogMap()
    {
        Id(x => x.Id, map => map.Generator(Generators.GuidComb));
        Property(x => x.ActivityDate);
        ManyToOne(x => x.Customer, mapping =>
        {

            mapping.Class(typeof(Customer));
            mapping.Column("CustomerId");

        });
    } 
}

也许有可能有一些扩展钩子和检查映射并手动为Nhibernate做?

编辑:这是如何使用EF

public class CustomerEFMap : EntityTypeConfiguration<Customer>
{
    public CustomerEFMap()
    {
        ToTable("Customer");
        HasKey(x => x.Id);
        Property(x => x.Name);
    }
}

public class ActivityLogEFMap : EntityTypeConfiguration<ActivityLog>
{
    public ActivityLogEFMap()
    {
        ToTable("ActivityLog");
        HasKey(x => x.Id);
        HasRequired(x => x.Customer).WithMany().HasForeignKey(x => x.CustomerId);
    }
}

using (var context = new ObjectContext())
        {
            var customer = context.Set<Customer>().Find(id);
            context.Set<Customer>().Remove(customer);

            context.SaveChanges();
        }

在DB中拥有Customer和相应的ActivityLog,同时删除

2 个答案:

答案 0 :(得分:0)

  

我希望能够删除客户和所有相应的   ActivityLog项目,通过调用

session.Delete(customer);
     

我不想要的是拥有属性列表登录   我的客户班。是否有可能在Nhibernate中实现?

NO。不可能,不打算,不支持。 NHibernate是ORM工具,可以/可以关心关系。没有关系,没有关心(没有级联)

但是,我们可以通过 protected

隐藏列表属性
public class Customer
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    // HIDDEN in fact from consumers, managed by NHibernate
    protected virtual IList<ActivitLog> { get; set; }
}

以及 cascade 的映射 - 将执行所需的操作。

答案 1 :(得分:0)

作为Radim Köhler states,我不认为有任何简单方式来映射级联行为而不实际拥有这种关系。但是,由于您的理由是基于插件的体系结构,因此可能需要使用部分类。

您可以将ActivityLog的集合作为受保护集合包含在插件DLL中作为分部类的一部分。如果您的映射然后映射集合,则删除Customer将删除ActivityLog

以下示例应该有效 - 请注意我使用FluentNhibernate进行映射。

此解决方案依赖于您能够将Customer类标记为部分。

using FluentAssertions;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate.Linq;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using System;
using System.Collections.Generic;

namespace MapTest
{
    public partial class Customer
    {
        public virtual Guid Id { get; set; }
        public virtual string Name { get; set; }
    }

    public class ActivityLog
    {
        public virtual Guid Id { get; set; }
        public virtual Customer Customer { get; set; }
        public virtual DateTime ActivityDate { get; set; }
    }

    public class CustomerMap : ClassMap<Customer>
    {
        public CustomerMap()
        {
            Id(x => x.Id).GeneratedBy.Guid();
            Map(x => x.Name);

            HasMany<ActivityLog>(Reveal.Member<Customer>("ActivityLogs")).Cascade.All();
        }
    }

    public class ActivityLogMap : ClassMap<ActivityLog>
    {
        public ActivityLogMap()
        {
            Id(x => x.Id).GeneratedBy.Guid();
            Map(x => x.ActivityDate);
            References(x => x.Customer);
        }
    }

    // Part of your plugin DLL
    public partial class Customer
    {
        protected virtual IList<ActivityLog> ActivityLogs { get; set; }
    }

    [TestFixture]
    public class PartialClassCascade
    {
        [Test]
        public void RunOnceToSetupDb()
        {
            Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2012.ConnectionString(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=MapTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
                .ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true))
                .BuildSessionFactory();
        }

        [Test]
        public void DeletingCustomerWithActivityLogs()
        {
            var sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2012.ConnectionString(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=MapTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
                .BuildSessionFactory();

            using (var session = sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                session.CreateQuery("delete ActivityLog a").ExecuteUpdate();
                session.CreateQuery("delete Customer c").ExecuteUpdate();

                tx.Commit();
            }

            var homerId = default(Guid);
            using (var session = sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var homer = new Customer
                {
                    Name = "Homer Simpson"
                };
                var monty = new Customer
                {
                    Name = "Monty Burns"
                };
                session.Save(homer);
                session.Save(monty);

                homerId = homer.Id;

                var activityLog1 = new ActivityLog
                {
                    Customer = homer,
                    ActivityDate = DateTime.Now,
                };
                var activityLog2 = new ActivityLog
                {
                    Customer = monty,
                    ActivityDate = DateTime.Now.AddDays(1),
                };
                session.Save(activityLog1);
                session.Save(activityLog2);

                tx.Commit();
            }

            using (var session = sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var customer = session.Get<Customer>(homerId);
                session.Delete(customer);

                tx.Commit();
            }

            using (var session = sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var customers = session.Query<Customer>();
                var activityLogs = session.Query<ActivityLog>();

                customers.Should().HaveCount(1);
                activityLogs.Should().HaveCount(1);
            }
        }
    }
}
相关问题