C# 编辑实体时未经NHibernate本人批准而保存
我有一个测试代码:C# 编辑实体时未经NHibernate本人批准而保存,c#,.net,nhibernate,C#,.net,Nhibernate,我有一个测试代码: int productId; { var codersAtWork = productService.Create(); codersAtWork.Title = "Coders At Work"; codersAtWork.Price = new Price(200, 160, 0.25m, "SEK"); codersAtWork.FieldBag.ReleaseDate = new DateTime(2009, 9, 1); p
int productId;
{
var codersAtWork = productService.Create();
codersAtWork.Title = "Coders At Work";
codersAtWork.Price = new Price(200, 160, 0.25m, "SEK");
codersAtWork.FieldBag.ReleaseDate = new DateTime(2009, 9, 1);
productService.Save(codersAtWork);
productId = codersAtWork.Id;
}
ReSetUp(); // Closes and opens a new session
{
var codersAtWork = productService.GetById(productId);
Assert.AreEqual(new DateTime(2009, 9, 1), codersAtWork.FieldBag.ReleaseDate);
codersAtWork.FieldBag.ReleaseDate = "Tomorrow";
Assert.Throws<InvalidFieldException>(() => { productService.Save(codersAtWork); });
var cleanCode = productService.Create();
cleanCode.Title = "Foo";
cleanCode.Price = new Price(300, 240, 0.25m, "SEK");
cleanCode.FieldBag.ReleaseDate = new DateTime(2009, 9, 1);
productService.Save(cleanCode); // This save will also save my incorrect product.
}
ReSetUp(); // Closes and opens a new session
{
var codersAtWork = productService.GetById(productId);
Assert.AreEqual(new DateTime(2009, 9, 1), codersAtWork.FieldBag.ReleaseDate);
}
int-productId;
{
var codersawork=productService.Create();
codersawork.Title=“工作中的编码器”;
Codersawork.Price=新价格(200,160,0.25百万瑞典克朗);
codersawork.FieldBag.ReleaseDate=新的日期时间(2009,9,1);
productService.Save(编码网络);
productId=codersAtWork.Id;
}
ReSetUp();//关闭并打开新会话
{
var codersawork=productService.GetById(productId);
Assert.AreEqual(新日期时间(2009年9月1日),Codersawork.FieldBag.ReleaseDate);
codersawork.FieldBag.ReleaseDate=“明天”;
Assert.Throws(()=>{productService.Save(codersAtWork);});
var cleanCode=productService.Create();
cleanCode.Title=“Foo”;
价格=新价格(300,240,0.25百万瑞典克朗);
cleanCode.FieldBag.ReleaseDate=新日期时间(2009,9,1);
productService.Save(cleanCode);//此保存还将保存我的错误产品。
}
ReSetUp();//关闭并打开新会话
{
var codersawork=productService.GetById(productId);
Assert.AreEqual(新日期时间(2009年9月1日),Codersawork.FieldBag.ReleaseDate);
}
我希望我的服务验证我发送给它的产品,并仅在有效时保存它。但问题是,当我在同一会话中保存其他有效的内容或在会话上调用Flush时,它将被保存,而我无法控制它是否有效。这里的最后一个断言将失败。product.FieldBag.ReleaseDate将为“明天”
FieldBag是动态的,并作为Json保存到数据库中。但这个问题也适用于其他验证
是否可以将NHibernate配置为仅保存我在上显式调用的项。SaveOrUpdate()您可以调用
Session.execute()
从会话中删除实体。然后NHibernate将忽略对这些实体的更改
或者,您可以使用
无状态会话获取/查询它们
您可以调用Session.execute()
从会话中删除实体。然后NHibernate将忽略对这些实体的更改
或者,您可以使用
无状态会话获取/查询它们
您可能需要使用事件处理程序来完成此操作。您可以使用PreInsertEventListener和PreUpdateEventListener。检查您的验证,如果验证未能否决该操作,则返回true
您可能需要使用事件处理程序来执行此操作。您可以使用PreInsertEventListener和PreUpdateEventListener。检查您的验证,如果验证未能否决该操作,则返回true
虽然您可以使用
会话.execute()退出对象
,但我建议您查看一下验证方法。如果我理解正确,那么您的productService.Save
方法将检查传入的对象是否有效。与使用某种类型的服务管理器检查对象是否有效不同,您应该将该验证移到对象本身中,并让对象确保它永远不会变为无效
例如:
class House
{
public Room Bedroom { get; set; }
}
class HouseService
{
public ValidateHouse(House aHouse) //There is no guarantee that this method is ever called
{
if (aHouse.Bedroom == null)
{
throw new InvalidFieldException();
}
}
}
在上面的例子中,您不能保证ValidateHouse曾经被调用过,因此也不能保证您有一个有效的房子要保存(或做任何事情)
将验证移到对象中:
class House
{
private Room theBedroom;
public Room Bedroom
{
get
{
return theBedroom;
}
set
{
if(value == null)
{
throw new ArgumentNullException();
}
theBedroom = value;
}
}
}
在本例中,保证卧室永远不会为空。如果有人试图将null赋值给卧室,则会抛出异常,并且对象永远不会更改。由于对象未更改,NHibernate不会尝试将其持久化。此外,这将使整个应用程序受益,因为您将知道对象始终处于有效状态
house.Bedroom = null;
house.Bedroom.ToString(); //With option 1 this will throw a NullPointerException.
house.Bedroom = null; //With option 2 this will throw an ArgumentNullException
//but your house object will still be in a known valid state.
house.Bedroom.ToString();
虽然您可以使用
Session.execute()
退出对象,但我建议您查看一下验证方法。如果我理解正确,那么您的productService.Save
方法将检查传入的对象是否有效。与使用某种类型的服务管理器检查对象是否有效不同,您应该将该验证移到对象本身中,并让对象确保它永远不会变为无效
例如:
class House
{
public Room Bedroom { get; set; }
}
class HouseService
{
public ValidateHouse(House aHouse) //There is no guarantee that this method is ever called
{
if (aHouse.Bedroom == null)
{
throw new InvalidFieldException();
}
}
}
在上面的例子中,您不能保证ValidateHouse曾经被调用过,因此也不能保证您有一个有效的房子要保存(或做任何事情)
将验证移到对象中:
class House
{
private Room theBedroom;
public Room Bedroom
{
get
{
return theBedroom;
}
set
{
if(value == null)
{
throw new ArgumentNullException();
}
theBedroom = value;
}
}
}
在本例中,保证卧室永远不会为空。如果有人试图将null赋值给卧室,则会抛出异常,并且对象永远不会更改。由于对象未更改,NHibernate不会尝试将其持久化。此外,这将使整个应用程序受益,因为您将知道对象始终处于有效状态
house.Bedroom = null;
house.Bedroom.ToString(); //With option 1 this will throw a NullPointerException.
house.Bedroom = null; //With option 2 this will throw an ArgumentNullException
//but your house object will still be in a known valid state.
house.Bedroom.ToString();