gpt4 book ai didi

c# - NHibernate尝试为FK映射插入现有记录,但仅当int ID为0时

转载 作者:太空宇宙 更新时间:2023-11-03 11:00:26 26 4
gpt4 key购买 nike

我正在使用消息传递系统,其中有一个名为Buffer的对象,该对象存储传入消息及其在系统中传播时的位置(用于消息跟踪)。我遇到了一些问题,这些问题表明我的应用程序或NHibernate根本存在问题。我正在使用Fluent NHibernate进行映射。

我有两个对象:Buffer和BufferMessageLocation。 Buffer是数据库中的一个表,每个记录代表一个缓冲消息(由代码中Buffer类的一个实例表示)。 BufferMessageLocation本质上是一个查找值,可以具有5个不同的值:0-4(每个值代表一个位置)。每个Buffer对象都包含一个BufferMessageLocation。 BufferMessageLocation在数据库中表示为Table [int ID,string Name]。

我必须进行一些分离的实体处理,因为我的应用程序中缓冲消息的寿命将比NHibernate会话的寿命更长。

这意味着:


打开新会话,从数据库中获取缓冲消息,关闭会话
在我的应用程序中进行一些处理,将缓冲区消息的位置更新为{ID = 0,Name =“ TestLocation”}。
打开新会话,通过调用Session.Load (0)获取新位置,关闭该会话。
将缓冲区消息的BufferMessageLocation更新为在步骤3中检索到的位置。
打开新的会话,在缓冲区消息上调用Session.Merge(buffer),关闭会话。


从我读到的有关NHibernate的所有内容来看,这应该有效。但是,由于某种原因,NHibernate试图将新记录插入BufferMessageLocation中,而不是仅更新Buffer记录。

这是错误消息:

could not insert: [AutomationBase.RepositoryNS.DataAccess.NHMG.Fluent.DTO.DBBufferMessageLocation][SQL: INSERT INTO tblBufferMessageLocation (Name) VALUES (?); select SCOPE_IDENTITY()]    


InnerException是:

Cannot insert the value NULL into column 'ID', table 'AutomationNew.dbo.tblBufferMessageLocation'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.


引发此错误的SQL是:

NHibernate: INSERT INTO tblBufferMessageLocation (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = 'TestLocation' [Type: String (4000)]


因此,每当我将缓冲区的位置更新为该值时,它似乎都将尝试插入具有Name =“ TestLocation”(已经存在)和ID = null的新BufferMessageLocation。这种情况有两件事:


当我仅引用刚从数据库中获得的记录时,为什么要插入新记录?
为什么在插入新记录时不提供BufferMessageLocation的ID的值?


值得注意的是,这仅在我将位置更新为ID = 0时发生。我尝试将Name =“ TestLocation”记录的ID更改为1,2,3,4和5,它们都可以工作。几乎每个ID值(除0之外)都起作用。我什至尝试将记录移至ID = 5,插入ID = 0的新BufferMessageLocation记录并将缓冲区消息的位置更新到此新记录,但是问题仍然存在。因此似乎ID = 0引起了NHibernate的记录检测机制的某些问题,因为所有其他int ID值都起作用。

还要注意的另一件事是,只有在使用多个会话时才会发生这种情况。如果我在一个会话中完成所有操作,则一切正常。我的猜测是,Session.Merge在调用合并分离的实体时无法检测到ID = 0的BufferMessageLocation。

如果有人对为什么会这样和/或这是NHibernate的问题或我做错了什么有任何想法,我将非常感谢您的反馈。我的代码完整如下。

抱歉,这么长的帖子,但这是一个非常具体的问题,因此我不得不详细介绍。

================================================== =======================

应用代码(请忽略类/对象名称上的“ DB”前缀,它们用于分层):

class Program
{
static void Main(string[] args)
{
DBBuffer dbBuffer;
DBInstruction instruction;
DBBufferMessageLocation bufferMessageLocation;

using (ISession session = FNHHelper.OpenSession())
{
using (ITransaction tran = session.BeginTransaction())
{
dbBuffer = session.QueryOver<DBBuffer>().List().First();
instruction = session.Load<DBInstruction>(2);
bufferMessageLocation = session.Load<DBBufferMessageLocation>(0);
tran.Commit();
}
}

//do application processing

dbBuffer.BufferMessageLocation = bufferMessageLocation;

//required attributes
dbBuffer.Instruction = instruction;
dbBuffer.Processed = false;
dbBuffer.FromProducer = false;

using (ISession session = FNHHelper.OpenSession())
{
using (ITransaction tran = session.BeginTransaction())
{
session.Merge(dbBuffer); <======== This is where the error is thrown
tran.Commit();
}
}
}
}


DTO类(用于此目的的域类):

public partial class DBBuffer : IRepositoryEntity 
{
public System.Guid ID { get; set; }
public DBLog Log { get; set; }
public DBError Error { get; set; }
public DBInstruction Instruction { get; set; }
public DBBufferMessageLocation BufferMessageLocation { get; set; }
public DateTime BufferTime { get; set; }
public string ClientIP { get; set; }
public string Description { get; set; }
public bool Processed { get; set; }
public bool FromProducer { get; set; }
}

public partial class DBBufferMessageLocation : IRepositoryLookup
{
public int ID { get; set; }
public string Name { get; set; }
public IList<DBBuffer> Buffers { get; set; }

public DBBufferMessageLocation()
{
Buffers = new List<DBBuffer>();
}
}


流水线图:

public partial class DBBufferMap : ClassMap<DBBuffer> {

public DBBufferMap() {
Table("tblBuffer");
Id(x => x.ID).GeneratedBy.Assigned().Column("ID");
References(x => x.Log).Column("LogID").Cascade.All();
References(x => x.Error).Column("ErrorID").Cascade.All();
References(x => x.Instruction).Column("InstructionID").Cascade.All();
References(x => x.BufferMessageLocation).Column("BufferMessageLocationID").Cascade.All();
Map(x => x.BufferTime).Column("BufferTime").Not.Nullable();
Map(x => x.ClientIP).Column("ClientIP");
Map(x => x.Description).Column("Description");
Map(x => x.Processed).Column("Processed").Not.Nullable();
Map(x => x.FromProducer).Column("FromProducer").Not.Nullable();
}
}

public partial class DBBufferMessageLocationMap : ClassMap<DBBufferMessageLocation> {

public DBBufferMessageLocationMap() {
Table("tblBufferMessageLocation");
Id(x => x.ID).GeneratedBy.Identity().Column("ID");
Map(x => x.Name).Column("Name").Not.Nullable();
HasMany(x => x.Buffers).KeyColumn("BufferMessageLocationID");
}
}

最佳答案

Id == 0被特殊视为“未设置ID”,将未设置的值更改为其他值,然后在构造函数中对其进行初始化

public DBBufferMessageLocationMap()
{
Id(x => x.ID, "ID").GeneratedBy.Identity().UnsavedValue(DBBufferMessageLocation.UNSET_ID);
}


public const int UNSET_ID = -1;
public DBBufferMessageLocation()
{
Id = UNSET_ID;
}

关于c# - NHibernate尝试为FK映射插入现有记录,但仅当int ID为0时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17863872/

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