Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiplicity constraint violated error while implementing chat functionality

I am implementing Chat functionality excatly like this one in asp.net.This is the model explaination Model is like this

My classes are: User, Conversaiton and Message:

public class User
{        
    public Guid Id { get; set; }
    public string Name { get; set; }
    public bool Active { get; set; }
    public string UserName { get; set; }       
    //keys       
    public ICollection<Conversation> Conversations { get; set; }
}
public class Conversation
{        
    public Guid ID { get; set; }
    public ICollection<Message> Messages { get; set; }
    public User RecipientUser { get; set; }
    public Guid SenderUserId { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime ModifiedDate { get; set; }
}

and finally,

public class Message
{

    public int ID { get; set; }
    public string Text { get; set; }
    public bool IsDelivered { get; set; }
    public bool IsSeen { get; set; }
    public Guid SenderUserId { get; set; }
    public Conversation Conversation { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime ModifiedDate { get; set; }
}

I am using EntityTypeConfiguration using fluent Api which are:

public class UserConfig : EntityTypeConfiguration<User>
{
    public UserConfig()
    {
        HasMany(x => x.Conversations).WithRequired(x => x.RecipientUser).HasForeignKey(x => x.SenderUserId);
    }
}
 public class ConversationConfig : EntityTypeConfiguration<Conversation>
{
    public ConversationConfig()
    {
        HasKey(x => x.ID);
        HasRequired(x => x.RecipientUser).WithMany(x => x.Conversations);
        HasMany(x => x.Messages).WithRequired(x => x.Conversation).HasForeignKey(x => x.SenderUserId);           
    }
}

But I'm getting error as follows: Multiplicity constraint violated. The role 'Conversation_RecipientUser_Target' of the relationship 'DataAcessLayer.Conversation_RecipientUser' has multiplicity 1 or 0..1.

If anyone could help me. Many thanks!!!

like image 732
Ajay Verma Avatar asked May 12 '26 19:05

Ajay Verma


1 Answers

I didn't get the exception when I used your model, but that doesn't matter much, because you've got to make some changes anyway.

First, this configuration in UserConfig ...

HasMany(x => x.Conversations).WithRequired(x => x.RecipientUser)
              .HasForeignKey(x => x.SenderUserId);

... doesn't make sense to me. This means that the conversations belong to the recipient, not to the sender, which in itself is somewhat unexpected. But the name of the foreign key is SenderUserId. If you save objects into this model, SenderUserId will get the value of the recipient's ID!

Second, assuming the previous point was an error, you make it harder than necessary by defining ...

public User RecipientUser { get; set; }
public Guid SenderUserId { get; set; }

This means that you can only navigate from Conversation to the sender User by an explicit join over SenderUserId. Conversely, you can only set the recipient by setting RecipientUser, not by simply setting a foreign key value.

Third, you shouldn't have this SenderUserId in Message. It should be ConversationId instead. You can find a Message's sender through the Conversation it belongs to.

All in all, I changed your model into this, reducing it to the bare-bone minimum, and using int for ID, just because it's easier reading:

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ICollection<Conversation> Conversations { get; set; }
}

public class Conversation
{
    public int ID { get; set; }
    public int SenderUserID { get; set; }
    public User SenderUser { get; set;}
    public int RecipientUserID { get; set; }
    public User RecipientUser { get; set; }
    public ICollection<Message> Messages { get; set; }
}

public class Message
{
    public int ID { get; set; }
    public string Text { get; set; }
    public int ConversationID { get; set; }
    public Conversation Conversation { get; set; }
}

And the only configuration:

public class ConversationConfig : EntityTypeConfiguration<Conversation>
{
    public ConversationConfig()
    {
        HasKey(c => c.ID);
        HasRequired(c => c.SenderUser).WithMany(u => u.Conversations)
                          .HasForeignKey(c => c.SenderUserID).WillCascadeOnDelete(true);
        HasRequired(c => c.RecipientUser).WithMany()
                          .HasForeignKey(c => c.RecipientUserID).WillCascadeOnDelete(false);
        HasMany(c => c.Messages).WithRequired(x => x.Conversation)
                      .HasForeignKey(x => x.ConversationID);
    }
}

(One of the foreign keys doesn't have cascaded delete because that will cause a SQL-Server error: multiple cascade paths).

A simple test:

using (DbContext db = new DbContext(connectionString))
{
    var send = new User { Name = "Sender" };
    db.Set<User>().Add(send);

    var rec = new User { Name = "Recipient" };
    var messages = new[] { new Message { Text = "a" }, new Message { Text = "b" } };
    var conv = new Conversation { SenderUser = send, RecipientUser = rec, Messages = messages };

    db.Set<User>().Add(rec);
    db.Set<Conversation>().Add(conv);

    db.SaveChanges();
}

Result:

Users:

ID    Name
1     Recipient
2     Sender

Converstions:

ID    RecipientUserID    SenderUserID
11    1                  2

Messages:

ID    Text    ConversationID
21    a       11
22    b       11
like image 89
Gert Arnold Avatar answered May 14 '26 08:05

Gert Arnold



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!