我正在使用Fluent Nhibernate,我收到以下错误:
"无法将值NULL插入列' EmailAccountId',table' NopCommerceNew123.dbo.QueuedEmail&#39 ;;列不允许空值。 INSERT失败。\ r \ n语句已终止。"}无法插入:[Nop.Core.Domain.Messages.QueuedEmail] [SQL:INSERT INTO QueuedEmail([Priority],[From],FromName,[ To],ToName,CC,Bcc,[Subject],Body,AttachmentFilePath,AttachmentFileName,CreatedOnUtc,SentTries,SentOnUtc,EmailAccountId)VALUES(?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?);选择SCOPE_IDENTITY()]
请告诉我这个错误。谢谢。
这是我的类和映射:
public partial class QueuedEmail : BaseEntity
{
/// <summary>
/// Gets or sets the priority
/// </summary>
public virtual int Priority { get; set; }
/// <summary>
/// Gets or sets the From property
/// </summary>
public virtual string From { get; set; }
/// <summary>
/// Gets or sets the FromName property
/// </summary>
public virtual string FromName { get; set; }
/// <summary>
/// Gets or sets the To property
/// </summary>
public virtual string To { get; set; }
/// <summary>
/// Gets or sets the ToName property
/// </summary>
public virtual string ToName { get; set; }
/// <summary>
/// Gets or sets the CC
/// </summary>
public virtual string CC { get; set; }
/// <summary>
/// Gets or sets the Bcc
/// </summary>
public virtual string Bcc { get; set; }
/// <summary>
/// Gets or sets the subject
/// </summary>
public virtual string Subject { get; set; }
/// <summary>
/// Gets or sets the body
/// </summary>
public virtual string Body { get; set; }
/// <summary>
/// Gets or sets the attachment file path (full file path)
/// </summary>
public virtual string AttachmentFilePath { get; set; }
/// <summary>
/// Gets or sets the attachment file name. If specified, then this file name will be sent to a recipient. Otherwise, "AttachmentFilePath" name will be used.
/// </summary>
public virtual string AttachmentFileName { get; set; }
/// <summary>
/// Gets or sets the date and time of item creation in UTC
/// </summary>
public virtual DateTime CreatedOnUtc { get; set; }
/// <summary>
/// Gets or sets the send tries
/// </summary>
public virtual int SentTries { get; set; }
/// <summary>
/// Gets or sets the sent date and time
/// </summary>
public virtual DateTime? SentOnUtc { get; set; }
/// <summary>
/// Gets or sets the used email account identifier
/// </summary>
public virtual int EmailAccountId { get; set; }
/// <summary>
/// Gets the email account
/// </summary>
public virtual EmailAccount EmailAccount { get; set; }
}
public partial class EmailAccount : BaseEntity
{
/// <summary>
/// Gets or sets an email address
/// </summary>
public virtual string Email { get; set; }
/// <summary>
/// Gets or sets an email display name
/// </summary>
public virtual string DisplayName { get; set; }
/// <summary>
/// Gets or sets an email host
/// </summary>
public virtual string Host { get; set; }
/// <summary>
/// Gets or sets an email port
/// </summary>
public virtual int Port { get; set; }
/// <summary>
/// Gets or sets an email user name
/// </summary>
public virtual string Username { get; set; }
/// <summary>
/// Gets or sets an email password
/// </summary>
public virtual string Password { get; set; }
/// <summary>
/// Gets or sets a value that controls whether the SmtpClient uses Secure Sockets Layer (SSL) to encrypt the connection
/// </summary>
public virtual bool EnableSsl { get; set; }
/// <summary>
/// Gets or sets a value that controls whether the default system credentials of the application are sent with requests.
/// </summary>
public virtual bool UseDefaultCredentials { get; set; }
public virtual ICollection<QueuedEmail> QueueEmail { get; set; }
/// <summary>
/// Gets a friendly email account name
/// </summary>
public virtual string FriendlyName
{
get
{
if (!String.IsNullOrWhiteSpace(this.DisplayName))
return this.Email + " (" + this.DisplayName + ")";
return this.Email;
}
}
public class QueuedEmailMap : ClassMap<QueuedEmail>
{
public QueuedEmailMap()
{
Table("QueuedEmail");
LazyLoad();
Id(x => x.Id).GeneratedBy.Identity().Column("Id");
Map(x => x.Priority).Column("[Priority]").Not.Nullable().Precision(10);
Map(x => x.From).Column("[From]").Not.Nullable().Length(500);
Map(x => x.FromName).Column("FromName").Length(500);
Map(x => x.To).Column("[To]").Not.Nullable().Length(500);
Map(x => x.ToName).Column("ToName").Length(500);
Map(x => x.CC).Column("CC").Length(500);
Map(x => x.Bcc).Column("Bcc").Length(500);
Map(x => x.Subject).Column("[Subject]").Length(1000);
Map(x => x.Body).Column("Body");
Map(x => x.AttachmentFilePath).Column("AttachmentFilePath");
Map(x => x.AttachmentFileName).Column("AttachmentFileName");
Map(x => x.CreatedOnUtc).Column("CreatedOnUtc").Not.Nullable();
Map(x => x.SentTries).Column("SentTries").Not.Nullable().Precision(10);
Map(x => x.SentOnUtc).Column("SentOnUtc");
//References(x => x.EmailAccount).Class<EmailAccount>().Columns("EmailAccountId");
References(x => x.EmailAccount).Column("EmailAccountId").Not.Nullable().Cascade.All();
}
}
public class EmailAccountMap : ClassMap<EmailAccount>
{
public EmailAccountMap()
{ Table("EmailAccount");
LazyLoad();
Id(x => x.Id).GeneratedBy.Identity().Column("Id");
Map(x => x.Email).Column("Email").Not.Nullable().Length(255);
Map(x => x.DisplayName).Column("DisplayName").Length(255);
Map(x => x.Host).Column("Host").Not.Nullable().Length(255);
Map(x => x.Port).Column("Port").Not.Nullable().Precision(10);
Map(x => x.Username).Column("Username").Not.Nullable().Length(255);
Map(x => x.Password).Column("Password").Not.Nullable().Length(255);
Map(x => x.EnableSsl).Column("EnableSsl").Not.Nullable();
Map(x => x.UseDefaultCredentials).Column("UseDefaultCredentials").Not.Nullable();
}
}
答案 0 :(得分:2)
此处的解决方案是在将EmailAccount
实例添加到 QueuedEmails 的集合中时分配QueuedEmail
。这应该是代码:
// method somewhere in the 'EmailAccount' definiton
public void AddEmail(QueuedEmail email)
{
this.QueueEmail.Add(email)
email.EmailAccount = this;
}
这将正确分配值&#34; EmailAccount&#34;进入专栏&#34; EmailAccountId&#34; INSERT期间。
原因是:我们将QueueEmail
的集合声明为反向
HasMany<QueuedEmail>(x => x.QueueEmail)
.KeyColumn("EmailAccountId")
.Inverse() // here we say inverse
.Cascade.All();
而逆是NHibernate的标志:孩子确实知道关于其父引用 - 孩子会关心关于自我(因为它有足够的信息)。通过(分配父母)上面的调整,一切都会有效。
&#34; not-null属性引用空值或瞬态值QueuedEmail.EmailAccount。&#34;
问题是,当我们致电:session.Save(queuedEmail)
时, queuedEmail 实例必须设置引用EmailAccount
。设置整数 EmailAccountId
是不够的!为什么?因为它没有映射。实际上有解决方案
所以,如果我们总能确定,我们有EmailAccountId
,我们就可以使用这种映射:
public class QueuedEmailMap : ClassMap<QueuedEmail>
{
public QueuedEmailMap()
{
...
// this property will be WRITABLE
Map(x => x.x.EmailAccountId)
.Column("EmailAccountId")
// this one will be readonly
References(x => x.EmailAccount)
.Column("EmailAccountId")
.Not.Nullable()
.Cascade.All()
.Not.Insert() // this is the setting
.Not.Update()
;
...
从这一刻起,我们可以只设置参考ID,并且一切都可以。
注意:我也使用doubled映射(Id和Reference),但readonly是int Id
答案 1 :(得分:0)
你可以像Radim说的那样两次添加属性。或者从EmailAccountId
类中删除属性QueuedEmail
,然后将其添加到您的映射中:
public class EmailAccountMap : ClassMap<EmailAccount>
{
public EmailAccountMap()
{
// your code
HasMany<QueuedEmail>(x => x.QueueEmail)
.KeyColumn("EmailAccountId")
.Inverse()
.Cascade.All();
}
}
public class QueuedEmailMap : ClassMap<QueuedEmail>
{
public QueuedEmailMap()
{
// your code
References(x => x.EmailAccount)
.Column("EmailAccountId")
.Not.Nullable();
}
}
别忘了打电话:
session.Save(emailAccount)