我的架构如下:
Id列是一个标识(1,1),而Message header表使用一个组合键,该组合键由关联的消息Id和一个header name字段组成,该字段唯一标识每个消息中的一个header。
实体在代码中表示为:
public class Message {
public virtual int Id { get; set; }
public virtual string Sender { get; set; }
public virtual string Recipient { get; set; }
private IList<MessageHeader> headers = new List<MessageHeader>();
public virtual IList<MessageHeader> Headers {
get { return headers; }
set { headers = value; }
}
public virtual void SetHeader(string headerName, string headerText) {
MessageHeader header = this.Headers.FirstOrDefault(h => h.HeaderName == headerName);
if (header == default(MessageHeader)) {
header = new MessageHeader() {
HeaderName = headerName,
Message = this
};
this.Headers.Add(header);
header.HeaderText = headerText;
}
}
}
public class MessageHeader {
public virtual Message Message { get; set; }
public virtual string HeaderName { get; set; }
public virtual string HeaderText { get; set; }
public virtual byte[] Version { get; set; }
public override bool Equals(object obj) {
if (Object.Equals(this, obj)) return (true);
var that = obj as MessageHeader;
if (that == null) return (false);
return (this.HeaderName == that.HeaderName && this.Message.Equals(that.Message));
}
public override int GetHashCode() {
return (this.HeaderName.GetHashCode() ^ this.Message.GetHashCode());
}
}
我想使用Fluent NHibernate映射这些实体,以便在运行以下代码时:
var message = new Message() { Sender = "alf", Recipient = "bob" };
message.SetHeader("DateSent", DateTime.Now.ToString());
using (var session = NHibernateHelper.GetCurrentSession()) {
using(var tx = session.BeginTransaction()) {
session.Save(message);
tx.Commit();
}
}
NHibernate将:
-
插入消息实体并检索标识值。
-
插入MessageHeader实体(在步骤1中检索到适当的MessageId)
我做不到。它要么尝试先插入MessageHeader(由于外键冲突而失败),要么尝试更新MessageHeader,而不是插入它,后者不返回任何行并抛出“无法将数据库状态与会话同步”错误。
我的FluentNH映射覆盖如下:
public class MessageOverrides : IAutoMappingOverride<Message> {
public void Override(AutoMapping<Message> map) {
map.HasMany(message => message.Headers).KeyColumn("MessageId");
}
}
public class MessageHeaderOverrides : IAutoMappingOverride<MessageHeader> {
public void Override(AutoMapping<MessageHeader> map) {
map.IgnoreProperty(header => header.Message);
map.CompositeId()
.KeyReference(header => header.Message, "MessageId")
.KeyProperty(header => header.HeaderName);
map.Version(header => header.Version)
.CustomSqlType("timestamp").Nullable()
.Generated.Always();
}
}
我以为将显式版本时间戳添加到MessageHeader表中可以解决这个问题,但它看起来不会。。。我肯定有些东西需要逆的或级联的或其他的,但是我完全不知道该去哪里。
迪伦