gpt4 book ai didi

nhibernate - 如何在使用 NHibernate 进行任何插入之前增加 ID

转载 作者:行者123 更新时间:2023-12-03 11:48:44 26 4
gpt4 key购买 nike

看起来 NH 只获得一次 MAX(ID),首先插入然后在内部存储这个值,这在其他进程插入数据时给我带来了一些问题。然后我没有实际的 ID 并引发重复键异常。

假设我们有表 Cats

CREATE TABLE Cats(ID int, Name varchar(25))

然后我们用 FluentNhibernate 完成了相应的映射
public class CatMap : ClassMap<Cat>
{
public CatMap()
{
Id(m=>m.ID).GeneratedBy.Increment();
Map(m=>.Name);
}
}

我想要实现的只是插入我的 Cat由 NHibernate 使用 SELECT MAX(ID) FROM Cats 生成 ID 的记录 在任何 之前插入。在任何提交 dosnt 工作后执行 Session.Flush。我已经使用 SQL Server 探查器进行了一些调查,并且这个 sql 语句只执行一次(在第一次插入时) - 其他插入不会强制检索实际的 MAX(ID)。我知道像 HiLo 这样的其他算法更好,但我无法替代它。

最佳答案

如您所见,NHibernate Increment id 生成器不适用于多用户环境。您声明使用 HiLo 生成器不是一个选项,因此您可以选择以下选项:

  • 使用 Native 生成​​器并更改 id 列以使用数据库支持的身份机制
  • 使用分配的生成器并编写代码来确定下一个有效 id
  • 创建一个自定义生成器,在其中实现 IIdentifierGenerator界面做你需要的

  • 下面是自定义生成器的示例代码,该生成器使用通用过程来获取给定表的 ID。这种方法的主要问题是您必须将代码包装在 Unit of Work 之类的东西中。模式以确保 'select max(id) ..."和插入被相同的数据库事务覆盖。 IIdentifierGenerator 链接具有连接此自定义生成器所需的 XML 映射。
    using System;
    using System.Collections.Generic;
    using System.Data;
    using NHibernate.Dialect;
    using NHibernate.Engine;
    using NHibernate.Id;
    using NHibernate.Persister.Entity;
    using NHibernate.Type;

    namespace YourCompany.Stuff
    {
    public class IdGenerator : IIdentifierGenerator, IConfigurable
    {
    private string _tableName;
    // The "select max(id) ..." query will go into this proc:
    private const string DefaultProcedureName = "dbo.getId";

    public string ProcedureName { get; protected set; }
    public string TableNameParameter { get; protected set; }
    public string OutputParameter { get; protected set; }

    public IdGenerator()
    {
    ProcedureName = DefaultProcedureName;
    TableNameParameter = "@tableName";
    OutputParameter = "@newID";
    }

    public object Generate(ISessionImplementor session, object obj)
    {
    int newId;
    using (var command = session.Connection.CreateCommand())
    {
    var tableName = GetTableName(session, obj.GetType());

    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = ProcedureName;

    // Set input parameters
    var parm = command.CreateParameter();
    parm.Value = tableName;
    parm.ParameterName = TableNameParameter;
    parm.DbType = DbType.String;

    command.Parameters.Add(parm);

    // Set output parameter
    var outputParameter = command.CreateParameter();
    outputParameter.Direction = ParameterDirection.Output;
    outputParameter.ParameterName = OutputParameter;
    outputParameter.DbType = DbType.Int32;

    command.Parameters.Add(outputParameter);

    // Execute the stored procedure
    command.ExecuteNonQuery();

    var id = (IDbDataParameter)command.Parameters[OutputParameter];

    newId = int.Parse(id.Value.ToString());

    if (newId < 1)
    throw new InvalidOperationException(
    string.Format("Could not retrieve a new ID with proc {0} for table {1}",
    ProcedureName,
    tableName));
    }

    return newId;
    }

    public void Configure(IType type, IDictionary<string, string> parms, Dialect dialect)
    {
    _tableName = parms["TableName"];
    }

    private string GetTableName(ISessionImplementor session, Type objectType)
    {
    if (string.IsNullOrEmpty(_tableName))
    {
    //Not set by configuration, default to the mapped table of the actual type from runtime object:
    var persister = (IJoinable)session.Factory.GetClassMetadata(objectType);

    var qualifiedTableName = persister.TableName.Split('.');
    _tableName = qualifiedTableName[qualifiedTableName.GetUpperBound(0)]; //Get last string
    }

    return _tableName;
    }
    }
    }

    关于nhibernate - 如何在使用 NHibernate 进行任何插入之前增加 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7887901/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com