Редактирование объекта сохраняется без моего согласия с NHibernate - PullRequest
0 голосов
/ 20 апреля 2011

У меня есть этот тестовый код:

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 будет "Tomorrow".

FieldBag является динамическим и сохраняется как Json в базе данных.Но проблема справедлива и для другой проверки.

Может ли NHibernate быть настроен на сохранение только тех элементов, которые я явно назвал .SaveOrUpdate () в

Ответы [ 3 ]

4 голосов
/ 20 апреля 2011

Вы можете позвонить Session.Evict(), чтобы удалить объекты из сеанса.Тогда NHibernate будет игнорировать изменения этих объектов.

В качестве альтернативы вы можете получить / запросить их с помощью StatelessSession.

1 голос
/ 20 апреля 2011

Вы можете использовать обработчики событий для этого. Вы можете использовать PreInsertEventListener и PreUpdateEventListener. Проверьте свою валидацию и верните true, если валидация не может наложить вето на действие.

http://www.nhforge.org/doc/nh/en/index.html#objectstate-events

0 голосов
/ 20 апреля 2011

Хотя вы можете выселить объект, используя 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;
        }
    }
}

В этом примере гарантируется, что спальня никогда не будет нулевой. Если кто-то пытается присвоить 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(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...