我在內存中的Sqlite有一些麻煩。release_mode,Pooling,InMemory SQLite的最大池大小與FluentNHibernate
我有一個有CPF字段的類 - 類似於美國的SSN。作爲商業規則,CPF在系統中必須是唯一的。
所以我決定檢查這個領域的課程。現在也許有代碼味道:我檢查ORM,如果這是一個衝突CPF。
private CPF cpf;
public virtual CPF CPF
{
get { return cpf; }
set
{
if (this.ormCreated) //Do not check if it is loaded from the DB. Otherwise, it loops, generating a StackOverflow exception
{
cpf = value;
}
else
{
this.setNewCpf(value);
}
}
}
private void setNewCpf(CPF newCpf)
{
if (this.cpf == newCpf)
{
return;
}
if (Helper.Orm.IsConflictingCpf(newCpf))
{
throw new ConflictingCpfException();
}
else
{
cpf = newCpf;
}
}
這裏是關於ORM Helper類的實現。
bool OrmHelper.IsConflictingCpf(CPF cpf)
{
int? cpfNumber = cpf.NumeroSemDV;
if (cpfNumber.HasValue)
{
var teste = findByCpfNumber<Client>(cpf);
return
(
findByCpfNumber<Client>(cpf) != null ||
findByCpfNumber<Adversary>(cpf) != null
);
}
else
{
//CPFSemDV = Nullable
return false;
}
}
private PersonType findByCpfNumber<PersonType> (CPF cpf) where PersonType : PessoaFisica
{
int? cpfNumber = cpf.NumeroSemDV;
using (var session = this.NewSession())
using (var transaction = session.BeginTransaction())
{
try
{
var person = session.Query<PersonType>()
.Where(c => c.CPF.NumeroSemDV == cpfNumber)
.FirstOrDefault<PersonType>();
return person;
}
catch (Exception) { transaction.Rollback(); }
finally
{
session.Close();
}
}
return null;
}
問題發生在我的測試中。我使用FluentNHibernate和內存SQLite。
protected override FluentConfiguration PersistenceProvider
{
get
{
return Fluently
.Configure()
.Database(
SQLiteConfiguration
.Standard
.InMemory()
.ShowSql()
);
}
}
這是失敗的測試。
protected override void Given()
{
base.Given();
var clients = new List<Client>();
Client client1 = new Client("Luiz Angelo Heinzen")
{
Capaz = true,
CPF = new CPF(18743509),
eMail = "[email protected]"
};
session.Save(client1);
session.Evict(client1);
}
[Then]
public void Motherfaker()
{
Client fromDb;
var clientsFromDb = session.Query<Client>()
.Where(c => c.eMail == "[email protected]");
fromDb = clientsFromDb.FirstOrDefault<Client>();
Assert.AreEqual(fromDb.FullName, "Luiz Angelo Heinzen");
}
它失敗的原因是什麼?在開始時它失敗了,因爲表格不存在。在內存中sqlite破壞每個新會話的架構。所以我改變了代碼以在NewSession()上返回同一個會話。但現在它失敗了一個NHibernate異常:Session關閉。我測試過,如果findByCpfNumber從這個
private PersonType findByCpfNumber<PersonType> (CPF cpf) where PersonType : PessoaFisica
{
int? cpfNumber = cpf.NumeroSemDV;
using (var session = this.NewSession())
using (var transaction = session.BeginTransaction())
{
try
{
var person = session.Query<PersonType>()
.Where(c => c.CPF.NumeroSemDV == cpfNumber)
.FirstOrDefault<PersonType>();
return person;
}
catch (Exception) { transaction.Rollback(); }
finally
{
session.Close();
}
}
return null;
}
改變這種
private PersonType findByCpfNumber<PersonType> (CPF cpf) where PersonType : PessoaFisica
{
int? cpfNumber = cpf.NumeroSemDV;
//using (var session = this.NewSession())
var session = this.NewSession();
using (var transaction = session.BeginTransaction())
{
try
{
var person = session.Query<PersonType>()
.Where(c => c.CPF.NumeroSemDV == cpfNumber)
.FirstOrDefault<PersonType>();
return person;
}
catch (Exception) { transaction.Rollback(); }
finally
{
//session.Close();
this.CloseSession(session);
}
}
this.CloseSession(session);
return null;
}
的錯誤不會再發生。顯然,我必須實現CloseSession方法。它會關閉生產數據庫中的會話,如果正在使用Sqlite,它將不會執行任何操作。
但我寧願配置SQLite在某種程度上它不會處理會話。我已閱讀here關於release_mode,Pooling和Max Pool的屬性。但我似乎無法在FluentNHibernate中找到它,所以甚至無法測試它是否可行。我克隆了FluentNHibernate,它似乎將release_mode設置爲on_close,但這沒有幫助。
我甚至試過:
public override ISession NewSession()
{
if (this.session == null)
{
if (sessionFactory == null)
{
CreateSessionFactory();
}
this.session = sessionFactory.OpenSession();
}
if (!session.IsOpen)
{
sessionFactory.OpenSession(session.Connection);
session.Connection.Open();
}
return session;
}
但它一直告訴我,會話關閉。那麼,任何人都有如何解決這個問題的建議?
還是這麼臭,這超出了救贖?
我希望這已經夠清楚了。並原諒我的錯誤:我來自巴西,而不是母語爲英語的人。
謝謝,
路易斯安傑洛。