nhibernate备用ID的使用生成的属性 [英] nhibernate alternate id's using generated properties

查看:88
本文介绍了nhibernate备用ID的使用生成的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

**这个问题已经过编辑,使其更简单,更集中**

** This question has been edited to make it simpler and more focused **

Employee有一个EmployeeNumberValue属性,我希望该属性由数据库自动递增.对于企业域,这是分配给员工的唯一ID,用于在员工卡等上标识他们.但是,对于数据库,它是备用ID,而不是主键.

Employee has an EmployeeNumberValue property which I would like to have auto-incremented by the db. To the business domain, this is a unique id assigned to employees and used to identify them on employee cards, etc. To the database however, it is an alternate id and not the primary key.

NHib具有记录的功能,称为生成的属性 . 根据文档,生成的属性是其值由数据库生成的属性.通常,NHibernate应用程序需要刷新对象,这些对象包含数据库正在为其生成值的任何属性.但是,将属性标记为已生成,则可以让应用程序委派此操作本质上,每当NHibernate对已定义生成属性的实体发出SQL INSERT或UPDATE时,它就会立即发出选择以检索生成的值."

NHib has a documented ability called Generated Properties. Per the docs, "generated properties are properties which have their values generated by the database. Typically, NHibernate applications needed to Refresh objects which contain any properties for which the database was generating values. Marking properties as generated, however, lets the application delegate this responsibility to NHibernate. Essentially, whenever NHibernate issues an SQL INSERT or UPDATE for an entity which has defined generated properties, it immediately issues a select afterwards to retrieve the generated values."

我遇到的问题是,尽管NHib进行了其他SELECT来更新EmployeeNumberValue,但它没有将检索到的值分配给该属性.

The problem I am having is that while NHib is making the additional SELECT to update the EmployeeNumberValue, it is not assigning the retrieved value to the property.

任何人都可以看到为什么会发生这种情况吗?

Can anyone see why this is happening what the fix is?

干杯,
贝里

失败的测试和输出(在内存数据库中经过SQLite测试):

FAILING TEST AND OUTPUT (tested w/ SQLite in memory db):

    [Test]
    public void Employee_OnInsert_EmployeeNumberValueIsIncremented() {

        var emp1 = new Employee
        {
            FullName = _fullName,
            Department = _department,
        };
        var emp2 = new Employee
        {
            FullName = _fullName,
            Department = _department,
        };

        var session = _SessionFactory.GetCurrentSession(); 

        using (var tx = session.BeginTransaction())
        {
            session.Save(_department);
            session.Save(emp1);
            session.Save(emp2);
            tx.Commit();
        }
        Assert.That(emp1.EmployeeNumberValue, Is.EqualTo(1));
        Assert.That(emp2.EmployeeNumberValue, Is.EqualTo(2));
    }

NHibernate: INSERT INTO Employees (FirstName, LastName, DepartmentId, EmployeeId) 
        VALUES (@p0, @p1, @p2, @p3);@p0 = 'Berryl' [Type: String (0)], @p1 = 'Hesh' [Type: String (0)], @p2 = 32768 [Type: Int32 (0)], @p3 = 65536 [Type: Int32 (0)]
NHibernate: SELECT employee_.EmployeeNumberValue as Employee2_1_ FROM Employees employee_ WHERE employee_.EmployeeId=@p0;@p0 = 65536 [Type: Int32 (0)]
NHibernate: INSERT INTO Employees (FirstName, LastName, DepartmentId, EmployeeId) 
        VALUES (@p0, @p1, @p2, @p3);@p0 = 'Berryl' [Type: String (0)], @p1 = 'Hesh' [Type: String (0)], @p2 = 32768 [Type: Int32 (0)], @p3 = 65537 [Type: Int32 (0)]
NHibernate: SELECT employee_.EmployeeNumberValue as Employee2_1_ FROM Employees employee_ WHERE employee_.EmployeeId=@p0;@p0 = 65537 [Type: Int32 (0)]
Test failed: 
   Expected: 1
   But was:  0

对象模型

public class Employee : Entity, IResource
{
    public virtual long EmployeeNumberValue { get; set; }

    ...
}

映射:

  <class name="Employee" table="Employees">

<id name="Id" unsaved-value="0">
  <column name="EmployeeId" />
  <generator class="hilo" />
</id>

<property name="EmployeeNumberValue" generated="insert" insert="false" update="false" >
  <column name="EmployeeNumberValue" sql-type="int IDENTITY(1,1)" index="IDX_EmployeeNumber"  />      
</property>

...

create table Employees (
    EmployeeId INTEGER not null,
   EmployeeNumberValue int IDENTITY(1,1),
   FirstName TEXT not null,
   LastName TEXT not null,
   DepartmentId INTEGER,
   primary key (EmployeeId)
)

我怀疑将列标记为IDENTITY的方式也令人怀疑.我尝试如下使用数据库对象,但这样做时出现使用错误

I suspect the way I am marking the column as IDENTITY is also suspect. I tried using database-object as below, but got a usage error in doing so

  <database-object>
    <create>
      ALTER TABLE Employee DROP COLUMN EmployeeNumberValue
      ALTER TABLE Employee ADD EmployeeNumberValue INT IDENTITY
    </create>
    <drop>
      ALTER TABLE Employee DROP COLUMN EmployeeNumberValue
    </drop>
  </database-object>

SQLiteException : SQLite error  "DROP": syntax error

推荐答案

从设计的角度来看,在这种情况下,我不会依赖NHibernate.我的意思是,在您的域模型中,您希望员工获得新的员工卡号.

From a design perpective I wouldn't rely on NHibernate in this case. What I mean is, that in your domain model, you want an employee to get a new employee card number.

在这种情况下,我只允许在有卡号的情况下实例化员工.

In this case I would only allow an employee to be instantiated if there is a card number.

public class EmployeeCardNumber
{
    private string id = String.Empty;
    internal EmployeeCardNumber(string id)
    {
        this.id = id;
    }
}


public class Employee
{
    private EmployeeCardNumber employeeCardNumber;

    public EmployeeCardNumber CardNumber { ... }

    public Employee(EmployeeCardNumber employeeCardNumber)
    {
        this.employeeCardNumber = employeeCardNumber;
    }
}

所以现在您必须考虑如何生成唯一的EmployeeCardNumber.

So now you have to think about how to generate a unique EmployeeCardNumber.

public class EmployeeCardNumberFactory
{
    public EmployeeCardNumber CreateNew()
    {
        // in this example the card number will be a guid.
        // but you could also implement a "EmployeeCardNumberGenerator" class which will do crazy database stuff
        return new EmployeeCardNumber(Guid.NewGuid().ToString());
    }
}

然后您以后再做:

EmployeeCardNumber cardNumber = employeeCardNumberFactory.CreateNew();
Employee employee = new Employee(cardNumber, name, etc...);

添加: 要通过数据库生成"EmployeeCardNumber",您可以将"EmployeeCardNumber"映射到一个额外的表"EmployeeCardNumber",该表将用作您的身份生成器,例如:

Addition: To generate a "EmployeeCardNumber" via database, you could just map "EmployeeCardNumber" to an extra table "EmployeeCardNumber" that will serve as your identity generator like:

<class name="EmployeeCardNumber" table="EmployeeCardNumber">
    <id name="id" access="field" unsaved-value="0">
      <column name="EmployeeCardNumberId" />
      <generator class="identity" />
    </id>
</class>

然后在工厂里可以做:

public class EmployeeCardNumberFactory
{
    private IEmployeeCardNumberRepository repository = new EmployeeCardNumberRepository(); // inject...
    public EmployeeCardNumber CreateNew()
    {     
        EmployeeCardNumber cardNumber = new EmployeeCardNumber();
        repository.Save(cardNumber); // gets you a fresh id
        return cardNumber;
    }
}

这篇关于nhibernate备用ID的使用生成的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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