如何使nhibernate cascade使用循环引用保存一组对象?

如何使nhibernate cascade使用循环引用保存一组对象?,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,我假设nhibernate可以处理循环引用问题,因为我没有在文档或谷歌上看到其他提及的内容(但可能我有错误的术语) 假设我有一个类,该类的成员引用其自身的一个实例: e、 g 然后我创建了两个对象,并让它们相互参照 A a1 = new A(); A a2 = new A(); a1.Other = a2; a2.Other = a1; 我想为这些类生成一组映射,这样,如果我试图在会话中保存a,它也会以保留b对a的引用的方式保存b 目前,我已经使用多对一关联生成了一个简单的映射(实际上这是由

我假设nhibernate可以处理循环引用问题,因为我没有在文档或谷歌上看到其他提及的内容(但可能我有错误的术语)

假设我有一个类,该类的成员引用其自身的一个实例:

e、 g

然后我创建了两个对象,并让它们相互参照

A a1 = new A();
A a2 = new A();

a1.Other = a2;
a2.Other = a1;
我想为这些类生成一组映射,这样,如果我试图在会话中保存a,它也会以保留b对a的引用的方式保存b

目前,我已经使用多对一关联生成了一个简单的映射(实际上这是由fluent nhibernate生成的,但在手动检查时看起来还可以)


但是当我保存时,a1不会在数据库中保存对a2的引用。我怎样才能让它这样做

这里有使用fluent nhibernate的示例代码(需要nhibernate、fluent nhibernate和nunit-如果有人想要精简版本,请告诉我)

我还创建了一个a3对象,它引用了它自己,这并不是我想要的保存

using System.IO;
using FluentNHibernate.Cfg;
using FluentNHibernate.Mapping;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;

namespace hibernate.experiment
{
    [TestFixture]
    public class CircularRefQn
    {
        [Test]
        public void Test()
        {
            var file = this.GetType().Name + ".db";
            if (File.Exists(file))
                File.Delete(file);

            var fcfg = Fluently.Configure()
                .Database(FluentNHibernate.Cfg.Db.SQLiteConfiguration.Standard
                              .UsingFile(file))
                              .Mappings(m =>
                              {
                                  m.FluentMappings.Add(typeof(A.Map));
                                  m.FluentMappings.ExportTo(".");
                              })
                              .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
                ;

            var sFactory = fcfg.BuildSessionFactory();


            using (var s = sFactory.OpenSession())
            {
                A a1 = new A();
                A a2 = new A();

                a1.Other = a2;
                a2.Other = a1;

                Assert.NotNull(a1.Other);
                Assert.NotNull(a2.Other);

                A a3 = new A();
                a3.Other = a3;

                s.Save(a1);
                s.Update(a1);
                s.Save(a3);
            }

            using (var s = sFactory.OpenSession())
            {
                foreach (var a in s.CreateCriteria(typeof(A)).List<A>())
                    Assert.NotNull(a.Other);
            }
        }

        public class A
        {
            public virtual int Id { get; set; }
            public virtual A Other { get; set; }

            public class Map : ClassMap<A>
            {
                public Map()
                {
                    Id(x => x.Id);
                    References(x => x.Other)
                        .Cascade.All();
                }
            }
        }


    }
}
使用System.IO;
使用FluentNHibernate.Cfg;
使用FluentNHibernate.Mapping;
使用NHibernate.Tool.hbm2ddl;
使用NUnit.Framework;
名称空间hibernate.experience
{
[测试夹具]
公共类通告
{
[测试]
公开无效测试()
{
var file=this.GetType().Name+“.db”;
如果(File.Exists(File))
文件。删除(文件);
var fcfg=fluntly.Configure()
.数据库(FluentNHibernate.Cfg.Db.SQLiteConfiguration.Standard
.UsingFile(文件))
.Mappings(m=>
{
m、 Add(typeof(A.Map));
m、 FluentMappings.ExportTo(“.”);
})
.ExposeConfiguration(cfg=>newschemaexport(cfg).Create(true,true))
;
var sFactory=fcfg.BuildSessionFactory();
使用(var s=sFactory.OpenSession())
{
a1=新的A();
a2=新的A();
a1.其他=a2;
a2.其他=a1;
Assert.NotNull(a1.Other);
Assert.NotNull(a2.Other);
a3=新的A();
a3.其他=a3;
s、 Save(a1);
s、 更新(a1);
s、 Save(a3);
}
使用(var s=sFactory.OpenSession())
{
foreach(s.CreateCriteria(typeof(a)).List()中的变量a)
Assert.NotNull(a.Other);
}
}
公共A类
{
公共虚拟整数Id{get;set;}
公共虚拟另一个{get;set;}
公共类映射:类映射
{
公共地图()
{
Id(x=>x.Id);
参考(x=>x.Other)
.Cascade.All();
}
}
}
}
}

始终在事务中执行插入/更新。下面是一个使用SQLite的工作示例:

using System;
using System.Data;
using System.IO;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate;

class Program
{
    static void Main(string[] args)
    {
        if (File.Exists("data.db3"))
        {
            File.Delete("data.db3");
        }

        using (var factory = CreateSessionFactory())
        {
            // Create schema and insert sample data
            using (var connection = factory.ConnectionProvider.GetConnection())
            {
                ExecuteQuery("create table users(usr_id integer primary key, other_id int, usr_name string)", connection);
            }

            using (var session = factory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                User u1 = new User() { Name = "User1" };
                User u2 = new User() { Name = "User2" };

                u1.Other = u2;
                u2.Other = u1;
                session.Save(u1);
                tx.Commit();
            }

            // Verify database state after inserts with ADO.NET
            using (var connection = factory.ConnectionProvider.GetConnection())
            using (var command = connection.CreateCommand())
            {
                command.CommandText = "select usr_id, other_id, usr_name from users";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine("usr_id: {0}, other_id: {1}, usr_name: {2}", reader.GetInt32(0), reader.GetInt32(1), reader.GetString(2));
                    }
                }
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(
                SQLiteConfiguration.Standard.UsingFile("data.db3").ShowSql()
            )
            .Mappings(
                m => m.FluentMappings.AddFromAssemblyOf<Program>()
            ).BuildSessionFactory();
    }

    static void ExecuteQuery(string sql, IDbConnection connection)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = sql;
            command.ExecuteNonQuery();
        }
    }
}

public class User
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual User Other { get; set; }
}

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        WithTable("users");
        Id(x => x.Id, "usr_id");
        Map(x => x.Name, "usr_name");
        References(x => x.Other)
            .ColumnName("other_id")
            .Cascade.All();
    }
}
使用系统;
使用系统数据;
使用System.IO;
使用FluentNHibernate.Cfg;
使用FluentNHibernate.Cfg.Db;
使用FluentNHibernate.Mapping;
使用NHibernate;
班级计划
{
静态void Main(字符串[]参数)
{
if(File.Exists(“data.db3”))
{
Delete文件(“data.db3”);
}
使用(var factory=CreateSessionFactory())
{
//创建模式并插入示例数据
使用(var connection=factory.ConnectionProvider.GetConnection())
{
ExecuteQuery(“创建表用户(usr\U id整数主键,其他\U id整数,usr\U名称字符串)”,连接);
}
使用(var session=factory.OpenSession())
使用(var tx=session.BeginTransaction())
{
用户u1=新用户(){Name=“User1”};
用户u2=新用户(){Name=“User2”};
u1.其他=u2;
u2.其他=u1;
session.Save(u1);
tx.Commit();
}
//使用ADO.NET验证插入后的数据库状态
使用(var connection=factory.ConnectionProvider.GetConnection())
使用(var command=connection.CreateCommand())
{
command.CommandText=“从用户中选择usr\U id、其他\U id、usr\U名称”;
使用(var reader=command.ExecuteReader())
{
while(reader.Read())
{
WriteLine(“usr_id:{0},other_id:{1},usr_name:{2}”,reader.GetInt32(0),reader.GetInt32(1),reader.GetString(2));
}
}
}
}
}
私有静态ISessionFactory CreateSessionFactory()
{
流畅地返回。Configure()
.数据库(
SQLiteConfiguration.Standard.UsingFile(“data.db3”).ShowSql()
)
.映射(
m=>m.FluentMappings.AddFromAssemblyOf()
).BuildSessionFactory();
}
静态void ExecuteQuery(字符串sql、IDbConnection)
{
使用(var command=connection.CreateCommand())
{
command.CommandText=sql;
command.ExecuteNonQuery();
}
}
}
公共类用户
{
公共虚拟整数Id{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟用户其他{get;set;}
}
公共类UserMap:ClassMap
{
公共用户映射()
{
WithTable(“用户”);
Id(x=>x.Id,“usr_Id”);
地图(x=>x.名称,“usr_名称”);
参考(x=>x.Other)
.ColumnName(“其他id”)
using System.IO;
using FluentNHibernate.Cfg;
using FluentNHibernate.Mapping;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;

namespace hibernate.experiment
{
    [TestFixture]
    public class CircularRefQn
    {
        [Test]
        public void Test()
        {
            var file = this.GetType().Name + ".db";
            if (File.Exists(file))
                File.Delete(file);

            var fcfg = Fluently.Configure()
                .Database(FluentNHibernate.Cfg.Db.SQLiteConfiguration.Standard
                              .UsingFile(file))
                              .Mappings(m =>
                              {
                                  m.FluentMappings.Add(typeof(A.Map));
                                  m.FluentMappings.ExportTo(".");
                              })
                              .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
                ;

            var sFactory = fcfg.BuildSessionFactory();


            using (var s = sFactory.OpenSession())
            {
                A a1 = new A();
                A a2 = new A();

                a1.Other = a2;
                a2.Other = a1;

                Assert.NotNull(a1.Other);
                Assert.NotNull(a2.Other);

                A a3 = new A();
                a3.Other = a3;

                s.Save(a1);
                s.Update(a1);
                s.Save(a3);
            }

            using (var s = sFactory.OpenSession())
            {
                foreach (var a in s.CreateCriteria(typeof(A)).List<A>())
                    Assert.NotNull(a.Other);
            }
        }

        public class A
        {
            public virtual int Id { get; set; }
            public virtual A Other { get; set; }

            public class Map : ClassMap<A>
            {
                public Map()
                {
                    Id(x => x.Id);
                    References(x => x.Other)
                        .Cascade.All();
                }
            }
        }


    }
}
using System;
using System.Data;
using System.IO;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate;

class Program
{
    static void Main(string[] args)
    {
        if (File.Exists("data.db3"))
        {
            File.Delete("data.db3");
        }

        using (var factory = CreateSessionFactory())
        {
            // Create schema and insert sample data
            using (var connection = factory.ConnectionProvider.GetConnection())
            {
                ExecuteQuery("create table users(usr_id integer primary key, other_id int, usr_name string)", connection);
            }

            using (var session = factory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                User u1 = new User() { Name = "User1" };
                User u2 = new User() { Name = "User2" };

                u1.Other = u2;
                u2.Other = u1;
                session.Save(u1);
                tx.Commit();
            }

            // Verify database state after inserts with ADO.NET
            using (var connection = factory.ConnectionProvider.GetConnection())
            using (var command = connection.CreateCommand())
            {
                command.CommandText = "select usr_id, other_id, usr_name from users";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine("usr_id: {0}, other_id: {1}, usr_name: {2}", reader.GetInt32(0), reader.GetInt32(1), reader.GetString(2));
                    }
                }
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(
                SQLiteConfiguration.Standard.UsingFile("data.db3").ShowSql()
            )
            .Mappings(
                m => m.FluentMappings.AddFromAssemblyOf<Program>()
            ).BuildSessionFactory();
    }

    static void ExecuteQuery(string sql, IDbConnection connection)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = sql;
            command.ExecuteNonQuery();
        }
    }
}

public class User
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual User Other { get; set; }
}

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        WithTable("users");
        Id(x => x.Id, "usr_id");
        Map(x => x.Name, "usr_name");
        References(x => x.Other)
            .ColumnName("other_id")
            .Cascade.All();
    }
}