我有这个测试代码:
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);
}
我希望我的服务验证我发送给它的产品,只有在它有效时才保存。但问题是,当我保存在同一会话中有效的其他内容或在会话上调用Flush时,它将保存,而我无法控制它是否有效。这里的最后一个断言将失败。 product.FieldBag.ReleaseDate将是“明天”。
FieldBag是动态的,并作为Json保存到数据库中。但问题也适用于其他验证。
可以将NHibernate配置为仅保存我在
上明确调用.SaveOrUpdate()的项目答案 0 :(得分:4)
您可以致电Session.Evict()
从会话中删除实体。然后NHibernate将忽略对这些实体的更改。
或者,您可以使用StatelessSession
来获取/查询它们。
答案 1 :(得分:1)
您可能希望使用事件处理程序来执行此操作。您可以使用PreInsertEventListener和PreUpdateEventListener。如果验证未能否决该操作,请检查您的验证并返回true。
http://www.nhforge.org/doc/nh/en/index.html#objectstate-events
答案 2 :(得分:0)
虽然您可以使用Session.Evict()
逐出该对象,但我建议您查看一下您的验证方法。如果我正确理解你,那么你的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;
}
}
}
在此示例中,保证Bedroom永远不会为空。如果有人试图将null分配给Bedroom,则抛出异常并且永远不会更改对象。由于对象没有被更改,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();