如何处理更新实体。 NHibernate的+ ASP.NET MVC [英] How to handle updating entities. NHibernate + ASP.NET MVC

查看:138
本文介绍了如何处理更新实体。 NHibernate的+ ASP.NET MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不能更新创建previously实体。我越来越有消息 StaleObjectException异常例外:

I cannot update created previously entity. I'm getting a StaleObjectException exception with message:

行被其它事务更新或删除(或者未保存价值的映射是不正确的):[Project.DomainLayer.Entities.Employee#00000000-0000-0000-0000-000000000000]

我不与任何人分享更新过程。有什么问题?

I don't share the update process with anyone. What's the problem?

数据访问/ DI

public class DataAccessModule : Ninject.Modules.NinjectModule
{
    public override void Load()
    {
        this.Bind<ISessionFactory>()
            .ToMethod(c => new Configuration().Configure().BuildSessionFactory())
            .InSingletonScope();

        this.Bind<ISession>()
            .ToMethod(ctx => ctx.Kernel.TryGet<ISessionFactory>().OpenSession())
            .InRequestScope();

        this.Bind(typeof(IRepository<>)).To(typeof(Repository<>))
            .InRequestScope();
    }
}

数据访问/映射

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Project.DomainLayer"   namespace="Project.DomainLayer.Entities">
<class name="Employee" optimistic-lock="version">
    <id name="ID" column="EmployeeID" unsaved-value="00000000-0000-0000-0000-000000000000">
        <generator class="guid.comb" />
    </id>
    <version name="Version" type="Int32" column="Version" />
    <!-- properties -->
    <property name="EmployeeNumber" />
    <!-- ... -->
    <property name="PassportRegistredOn" not-null="true" />
    <!-- sets -->
    <set name="AttachedInformation" cascade="all">
        <key column="EmployeeID" />
        <element column="Attachment" />
    </set>
    <set name="TravelVouchers" cascade="all">
        <key column="EmployeeID" />
        <one-to-many class="TravelVoucher" />
    </set>
  </class>
</hibernate-mapping>

数据访问/存储库

public class Repository<T> : IRepository<T> where T : AbstractEntity<T>, IAggregateRoot
{
    private ISession session;

    public Repository(ISession session)
    {
        this.session = session;
    }

    // other methods are omitted

    public void Update(T entity)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Update(entity);
            transaction.Commit();
        }
    }
    public void Update(Guid id)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Update(this.session.Load<T>(id));
            transaction.Commit();
        }
    }
} 

里面一个控制器

public class EmployeeController : Controller
{
    private IRepository<Employee> repository;

    public EmployeeController(IRepository<Employee> repository)
    {
        this.repository = repository;
    }        
    public ActionResult Edit(Guid id)
    {
        var e = repository.Load(id);
        return View(e);
    }
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Employee employee)
    {
        if(ModelState.IsValid)
        {
            repository.Update(employee);
            return RedirectToAction("Deatils", "Employee", new { id = employee.ID });
        }
        else
        {
            return View(employee);
        }
    }
}

如何更新我的实体?
谢谢!

How do I update my entities? Thanks!

修改

所以我添加未保存值={Guid.Empty放在这里}我的标记。而且我一直试图做的下一件事:

So I added unsaved-value="{Guid.Empty goes here}" to my markup. Moreover I've tried to do the next thing:

public void Update(T entity)
{
    using(var transaction = this.session.BeginTransaction())
    {
        try
        {
            this.session.Update(entity);
            transaction.Commit();
        }
        catch(StaleObjectStateException ex)
        {
            try
            {
                session.Merge(entity);
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }

    }
}

这使我有同样的效果。我的意思是器transaction.commit(); 合并给出同样的异常。

此外,我不知道我应该公开,采用隐藏式输入,实体 ID 修改看法?

Also I'm wondering should I expose, using hidden input, the entity ID on the Edit view?

修改

所以,真正的实体分离。当它传递给控制器​​ ID 等于 Guid.Empty 。我该如何处理它,合并重新连接

So entity really detaches. When it passes to controller the ID equals Guid.Empty. How do I handle it, Merge or Reattach?

推荐答案

有,你可以遇到两种情况,鉴于你code模式。

There are two scenarios that you can run into, given your code pattern.

1)你可以检索从使用ISession.Get分贝可被随后的改变/更新检索到的对象的对象。对于这种变化是有效的,所有你需要做的就是刷新会话或承诺例如NHibernate会自动跟踪所有你更改的事务。

1)You could retrieve the object from the db using ISession.Get which can be followed by a change/update to the retrieved object. For this change to be effective, all you need to do is flush the session or commit the transaction as Nhibernate will track all the changes for you automatically.

2)你有一个短暂的实例,即不与ISession的上下文中,从其中要更新相关联的对象。在这种情况下,从我的经验,最好的做法是ISession.Get对象和让你只检索对象的相应变化。(通常是您的视图模型是从你的域模型不同为好,不要混用两种)这种模式如下所示。它的工作原理所有的时间。请确保您还使用ISession.SaveOrUpdate。

2)You have a transient instance, an object that is not associated with the ISession in context, from which you want to update. In this case, from my experience, the best practice is to ISession.Get the object and the make the corresponding changes to the object you just retrieve.(usually your view model is different from your domain model as well, don't mix both ) This pattern is shown below. It works all the time. Make sure you also use ISession.SaveOrUpdate.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Employee employee)
{
    if(ModelState.IsValid)
    {
        var persistentEmployee = repository.Get(employee.Id);
        if(  persistentEmployee == null){
            throw new Exception(String.Format("Employee with Id: {0} does not exist.", employee.Id));
        }
        persistentEmployee.Name = employee.Name;
        persistentEmployee.PhoneNumber = employee.PhoneNumber;
        //and so on
        repository.Update(persistentEmployee);
        return RedirectToAction("Deatils", "Employee", new { id = employee.ID });
    }
    else
    {
        return View(employee);
    }
}

另外,注意你的控制器可能实例化每个请求的基础,因此,您的ISession的寿命不会跨越你在你的控制器有不同的方法多次调用。换句话说,每个方法几乎都是一个新的ISession(工作单位)的范围内正常工作。

Also, notice that your controller is probably instantiated on a per request basis, hence, the lifetime of your ISession does not span multiple calls to the different methods you have in your controller. In other words, every method is almost always working within the context of a new ISession (unit of work).

这篇关于如何处理更新实体。 NHibernate的+ ASP.NET MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆