如何在NHibernate的做版本? [英] How do you do Versioning in Nhibernate?

查看:172
本文介绍了如何在NHibernate的做版本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不能相信它是如此难以得到别人告诉我一个简单的工作示例。这使我相信,每个人都只能那样说话,他们知道该怎么做,但在现实中并非如此。

我缩短后下降到仅是我想做的例子做。也许后是越来越长和害怕的人了。

要获得此奖金我找工作的例子,我可以在VS 2010中复制和运行。

什么例子需要做的。


  1. 显示应该是什么样的数据类型在我的域版本作为时间戳 2008年MSSQL

  2. 显示NHibernate的自动抛StaleObjectException异常

  3. 显示我的这3个方案工作示例

情景1

用户A来到现场和编辑ROW1。用户B来(注:他能看到ROW1),并点击编辑从,直到用户A完成编辑行ROW1,用户B应该被拒绝。

情景2

用户A来到现场和编辑ROW1。用户B是后话30分钟,并单击编辑ROW1。用户B应该可以编辑该行并保存。这是因为用户A的时间太长编辑该行并失去了他的编辑权。

情景3

用户A被走回来。他点击更新按钮行,他应该与StaleObjectException异常相迎。

我使用asp.net MVC和连贯NHibernate。寻找的例子在这些工作要做。


我试过

我试图建立自己的,但我不能把它扔StaleObjectException异常,也没有我可以得到的版本号递增。我累了开幕2个独立的浏览器,并装载了索引页。两种浏览器表现出相同的版本号。

 公共类Default1Controller:控制器
{
    //
    // GET:/缺省1 /    公众的ActionResult指数()
    {
        VAR SessionFactory的= CreateSessionFactory();        使用(VAR会话= sessionFactory.OpenSession())
        {
            使用(VAR交易= session.BeginTransaction())
            {
                VAR firstRecord = session.Query<表A>()FirstOrDefault()。
                器transaction.commit();
                返回查看(firstRecord);
            }        }    }    公众的ActionResult保存()
    {
        VAR SessionFactory的= CreateSessionFactory();
        使用(VAR会话= sessionFactory.OpenSession())
        {
            使用(VAR交易= session.BeginTransaction())
            {
                VAR firstRecord = session.Query<表A>()FirstOrDefault()。
                firstRecord.Name =测试2;
                器transaction.commit();
                返回查看();
            }
        }
    }    私有静态ISessionFactory CreateSessionFactory()
    {
        返回Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008
                .ConnectionString(C => c.FromConnectionStringWithKey(测试)))
            .Mappings(M = GT; m.FluentMappings.AddFromAssemblyOf<表A>())
                             // .ExposeConfiguration(BuidSchema)
            .BuildSessionFactory();
    }
    私有静态无效BuidSchema(NHibernate.Cfg.Configuration配置)
    {
        新NHibernate.Tool.hbm2ddl.SchemaExport(配置).Create(假,真);
    }}
公共类TableA的
{
    公共虚拟的Guid标识{搞定;组; }
    公共虚拟字符串名称{;组; }    //不知道什么数据类型,这应该是时间戳。
    //为了消除转变为多开始与INT版本
    //但到底想时间戳。
    公共虚拟INT版本{搞定;组; }
}公共类TableAMapping:ClassMap<表A>
{
    公共TableAMapping()
    {
        ID(X => x.Id);
        地图(X => x.Name);
        版本(X => x.Version);
    }
}


解决方案

  

NHibernate的会被检索停止行?


没有。锁只放置一个事务,这在Web应用程序的请求结束时结束的程度。此外,交易隔离模式的默认类型是读致力于这意味着读锁尽快发布select语句终止。如果你正在阅读,并在相同的请求和交易进行编辑,你可以放置一个读,手头这将美元,写入或从该行读取p $ pvent其他交易写在行锁。然而,这种类型的并发控制不能很好在Web应用程序的工作。


  

或者将用户B可以仍看到行,但如果他试图挽救它会崩溃?


如果正在使用[乐观并发]在这会发生。在NHibernate中,乐观并发的工作方式是添加<一个href=\"http://nhforge.org/blogs/nhibernate/archive/2009/04/15/nhibernate-mapping-concurrency.aspx\">version现场。保存/更新命令与在其上更新所依据的版本发行。如果从数据库表中的版本不同,没有行被更新和NHibernate会抛出。


  

如果用户A说取消并没有编辑会发生什么。我一定要吗
  解除锁定自己还是有超时可以设置为释放
  锁?


没有,锁被释放的请求结束。

总体而言,最好的办法是选择乐观并发与NHibernate的管理版本字段。

I can't believe it is so hard to get someone to show me a simple working example. It leads me to believe that everyone can only talk like they know how to do it but in reality they don't.

I shorten the post down to only what I want the example to do. Maybe the post was getting to long and scared people away.

To get this bounty I am looking for a WORKING EXAMPLE that I can copy in VS 2010 and run.

What the example needs to do.

  1. Show what datatype should be in my domain for version as a timestamp in mssql 2008
  2. Show nhibernate automatically throwing the "StaleObjectException"
  3. Show me working examples of these 3 scenarios

Scenario 1

User A comes to the site and edits Row1. User B comes(note he can see Row1) and clicks to edit Row1, UserB should be denied from editing the row until User A is finished.

Scenario 2

User A comes to the site and edits Row1. User B comes 30mins later and clicks to edit Row1. User B should be able to edit this row and save. This is because User A took too long to edit the row and lost his right to edit.

Scenario 3

User A comes back from being away. He clicks the update row button and he should be greeted with StaleObjectException.

I am using asp.net mvc and fluent nhibernate. Looking for the example to be done in these.


What I tried

I tried to build my own but I can't get it throw the StaleObjectException nor can I get the version number to increment. I tired opening 2 separate browser and loaded up the index page. Both browsers showed the same version number.

public class Default1Controller : Controller
{
    //
    // GET: /Default1/

    public ActionResult Index()
    {
        var sessionFactory = CreateSessionFactory();

        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var firstRecord = session.Query<TableA>().FirstOrDefault();
                transaction.Commit();
                return View(firstRecord);
            }

        }

    }

    public ActionResult Save()
    {
        var sessionFactory = CreateSessionFactory();
        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var firstRecord = session.Query<TableA>().FirstOrDefault();
                firstRecord.Name = "test2";
                transaction.Commit();
                return View();
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008
                .ConnectionString(c => c.FromConnectionStringWithKey("Test")))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<TableA>())
                             //  .ExposeConfiguration(BuidSchema)
            .BuildSessionFactory(); 
    }


    private static void BuidSchema(NHibernate.Cfg.Configuration config)
    {
        new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
    }

}


public class TableA
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }

    // Not sure what data type this should be for timestamp.
    // To eliminate changing to much started with int version
    // but want in the end timestamp.
    public virtual int Version { get; set; } 
}

public class TableAMapping : ClassMap<TableA>
{
    public TableAMapping()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        Version(x => x.Version);
    }
}

解决方案

Will nhibernate stop the row from being retrieved?

No. Locks are only placed for the extent of a transaction, which in a web application ends when the request ends. Also, the default type of transaction isolation mode is Read committed which means that read locks are released as soon as the select statement terminates. If you are reading and making edits in the same request and transaction, you could place a read and write lock on the row at hand which would prevent other transactions from writing to or reading from that row. However, this type of concurrency control doesn't work well in a web application.

Or would the User B be able to still see the row but if he tried to save it would crash?

This would happen if [optimistic concurrency] was being used. In NHibernate, optimistic concurrency works by adding a version field. Save/update commands are issued with the version upon which the update was based. If that differs from the version in the database table, no rows are updated and NHibernate will throw.

What happens if User A say cancels and does not edit. Do I have to release the lock myself or is there a timeout can be set to release the lock?

No, the lock is released at the end of the request.

Overall, your best bet is to opt for optimistic concurrency with version fields managed by NHibernate.

这篇关于如何在NHibernate的做版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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