1

I am working on Fluent Nhibernate and I am getting the following error:

"Cannot insert the value NULL into column 'EmailAccountId', table 'NopCommerceNew123.dbo.QueuedEmail'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."} could not insert: [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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); select SCOPE_IDENTITY()]

Please let me know about the error in this.Thanks.

Here Are My Classes and mappings:

QueueEmail.cs

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; } } 

EmailAccount.cs

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; } } 

QueuedEmailMap.cs:

 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(); } } 

EmailAccountMap.cs:

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(); } } 
3
  • 1
    Can you show the full exception? Commented May 13, 2014 at 19:32
  • @Najera This is the full exception :{"Cannot insert the value NULL into column 'EmailAccountId', table 'NopCommerceNew123.dbo.QueuedEmail'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."} could not insert: [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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); select SCOPE_IDENTITY()] Please check it. Thanks. Commented May 14, 2014 at 4:06
  • @Najera : Now I am getting the following error for the above class: "not-null property references a null or transient value QueuedEmail.EmailAccount.". Please help me to solve it out. Thanks. Commented May 15, 2014 at 11:11

2 Answers 2

2

The solution here would be to assign EmailAccount of the QueuedEmail instance, when adding it into the collection of QueuedEmails. This should be the code:

// method somewhere in the 'EmailAccount' definiton public void AddEmail(QueuedEmail email) { this.QueueEmail.Add(email) email.EmailAccount = this; } 

this will correctly assign the value "EmailAccount" into the column "EmailAccountId" during the INSERT.

The reason is: we declared the collection of QueueEmail as inverse

HasMany<QueuedEmail>(x => x.QueueEmail) .KeyColumn("EmailAccountId") .Inverse() // here we say inverse .Cascade.All(); 

And inverse is a sign for NHibernate: the child does know about its parent reference - child will care about self (because it has enough information). And with the adjustment above (assigning the parent) all will work.

EDIT: how to fix the next issue:

"not-null property references a null or transient value QueuedEmail.EmailAccount."

The problem is, that when we call: session.Save(queuedEmail) the queuedEmail instance must have set the reference EmailAccount. It is not enough to set integer EmailAccountId! Why? because it is not mapped. And there is in fact solution

So, if we always can be sure, that we have the EmailAccountId, we can use this mapping:

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() ; ... 

From this moment, we can set just the reference Id and all will work.

NOTE: I do also use the doubled mapping (Id and Reference), but the readonly is the int Id

Sign up to request clarification or add additional context in comments.

6 Comments

Now, I am getting the following error in this : "not-null property references a null or transient value QueuedEmail.EmailAccount." Please help to solve it out.
What is your code, where you get the exception? are you calling session.Save(queuedEmail)? if yes... you have to call the session.Save(emailAccount) ... the parent. This way, NHibernate will firstly store the EmailAccount and have its ID. it will be then used for queuedEmail as a reference Id...
Yes, I am passing session.Save(QueuedEmail) but I have EmailAccountId in this. Also The EmailAccount object is null. So can also cause error. If yes, then how can I been able to solve it. Please check the mapping above i had made some small changes.
I tried to show you how - in my EDIT. We can map anything twice... but one of the mapping must be readonly
@RadimKöhler Why you like map twice?
|
0

You can add the property twice like Radim says. Or delete the property EmailAccountId from QueuedEmail class and just add this to your mapping:

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(); } } 

Don't forget call:

session.Save(emailAccount) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.