我正面临着Repository和Transactions的异常行为 它让我很生气。
我有两个简单的POCO类Action和Version如下。有 来自Action->版本的一对多关系。
public class Action : Entity
{
public virtual string Name
{
get;
set;
}
public virtual IList<Version> Versions
{
get;
protected set;
}
public Action()
{
Versions = new List<Version>();
}
public virtual void AddVersion( Version version )
{
version.Action = this;
Versions.Add( version );
}
}
public class Version : Entity
{
public virtual int Number
{
get;
set;
}
public virtual Action Action
{
get;
set;
}
public Version()
{
}
}
现在我有一个代码段如下:
var actionRep = new Repository<Action>();
var versionRep = new Repository<Version>();
var act1 = new Action( );
actionRep .SaveOrUpdate( act1 );
using (versionRep .DbContext.BeginTransaction())
{
var v1 = new Version();
act1.AddVersion( v1 );
//versionRep .SaveOrUpdate( v1 );
versionRep .DbContext.CommitTransaction();
}
在上面的代码中,我只是创建Action和Version存储库。 首先,我使用Action Repository持久化Action对象。然后我开始 使用Version repository的事务,创建一个新版本,set 带有Action的引用,并且在没有的情况下提交事务 实际上调用版本库。
结果有点奇怪。版本对象甚至可以持久化 虽然我没有在版本库上调用SaveOrUpdate方法。如果 我注释掉了行act1.AddVersion(v1);在交易中, 然后版本不会持久化。
经过一番努力,我使用NHibernate测试了相同的场景 直接而不是使用Sharp Architecture存储库使用相同的 流畅的映射/配置 (AutoPersistenceModelGenerator.Generate())。结果如下 预期。版本对象不会持久化。这是代码
var sessionFactory = CreateSessionFactory();
_act1 = new Action();
using( var session = sessionFactory.OpenSession() )
{
session.SaveOrUpdate( _act1 );
}
using( var session = sessionFactory.OpenSession() )
{
using (var transaction = session.BeginTransaction())
{
_v1 = new Version();
_act1.AddVersion( _v1 );
//session.SaveOrUpdate( _act1 );
transaction.Commit();
}
}
CreateSessionFactory()方法如下。没什么复杂的
private const string _dbFilename = "nhib_auditing.db";
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database( SQLiteConfiguration.Standard
.UsingFile( _dbFilename )
.ShowSql())
.Mappings( m => m.AutoMappings.Add( new
AutoPersistenceModelGenerator().Generate() ) )
.ExposeConfiguration( BuildSchema )
.BuildSessionFactory();
}
现在如果sombody可以请让我知道为什么我这样做 行为。它让我很生气。
只是为了让你知道我没有覆盖Action和的映射 版本要么。
等待 纳贝尔
答案 0 :(得分:4)
如果您在映射中声明了级联操作,则这是预期的行为。当您在act1上调用SaveOrUpdate
时,您使瞬态对象持久化;也就是说,NHibernate会跟踪它并在刷新会话时保存它。使对象持久化的另一种方法是将其与持久对象相关联,就像调用act1.AddVersion( v1 );
时所做的那样。提交事务时会话被刷新,因此保存了v1。 This article解释了使用持久对象的细节。
答案 1 :(得分:0)
顺便说一下,这是我用SharpRepositories进行的两次测试 失败了,以及NHibernate Directly正在通过。
[TestFixture]
public class RepositoryTests : RepositoryTestsBase
{
protected override void LoadTestData()
{
}
[Test]
public void TestUsingSharpRespositories
{
var aRep = new Repository<Action>();
var vRep = new Repository<Version>();
_act1 = new Action();
aRep.SaveOrUpdate( _act1 );
using( vRep.DbContext.BeginTransaction() )
{
_v1 = new Version();
_act1.AddVersion( _v1 );
//vRep.SaveOrUpdate(_v1);
vRep.DbContext.CommitTransaction();
}
_v1.IsTransient().ShouldBeTrue();
}
[Test]
public void TestUsingNHibernateSession
{
var sessionFactory = CreateSessionFactory();
_act1 = new Action();
using( var session = sessionFactory.OpenSession() )
{
session.SaveOrUpdate( _act1 );
}
using( var session = sessionFactory.OpenSession() )
{
using (var transaction = session.BeginTransaction())
{
_v1 = new Version();
_act1.AddVersion( _v1 );
transaction.Commit();
}
}
_v1.IsTransient().ShouldBeTrue();
}
private const string _dbFilename = "nhib_db.db";
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database( SQLiteConfiguration.Standard
.UsingFile( _dbFilename )
.ShowSql())
.Mappings( m => m.AutoMappings.Add( new
AutoPersistenceModelGenerator().Generate() ) )
.ExposeConfiguration( BuildSchema )
.BuildSessionFactory();
}
private static void BuildSchema( Configuration config )
{
if( File.Exists( _dbFilename ) )
File.Delete( _dbFilename );
new SchemaExport( config ).Create( false, true );
}
}
我是Fluent NHibernate的新手,我从未直接使用NHibernate进行xml映射。
就映射而言,我正在使用在Visual Studio中创建新的Sharp Architecture项目时设置的vanilla自动配置。我有一个HasMany的约定如下:
public class HasManyConvention : IHasManyConvention
{
public void
Apply( FluentNHibernate.Conventions.Instances.IOneToManyCollectionInstance
instance )
{
instance.Key.Column( instance.EntityType.Name + "Fk" );
instance.Inverse();
instance.Cascade.All();
}
}
我按如下方式更新了我的TestUsingNHibernateSession测试,以测试在单个会话中操作Action和Version时的行为方式。并猜测,即使在事务的开始和提交之间没有任何内容,Version对象也会被保存。
[Test]
public void TestUsingNHibernateSession
{
var sessionFactory = CreateSessionFactory();
_act1 = new Action();
using( var session = sessionFactory.OpenSession() )
{
session.SaveOrUpdate( _act1 );
//}
//using( var session = sessionFactory.OpenSession() )
//{
_v1 = new Version();
_act1.AddVersion( _v1 );
using (var transaction = session.BeginTransaction())
{
transaction.Commit();
}
}
_v1.IsTransient().ShouldBeTrue();
}
所以我的结论是它与会话有关。如果在会话中创建或检索了对象A,然后如果在该会话中开始新事务,则在提交该事务后,与对象A关联的所有瞬态或脏对象也会被保存,否则在Begin和Commit之内或之外创建了更好的对象。
如果他们同意我的理解,有人可以告诉我吗?我还假设Sharp架构在每个Web请求中使用单个nhibernate会话?
等待 纳贝尔