我正在asp.net中像这一样兴奋地实现Chat functionality。这是模型解释
我的课程是:用户,对话和留言:
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; }
}
最后,
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; }
}
我使用流畅的Api使用EntityTypeConfiguration:
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);
}
}
但我收到的错误如下: 违反了多重约束。 “DataAcessLayer.Conversation_RecipientUser”关系的“Conversation_RecipientUser_Target”角色具有多重性1或0..1。
如果有人可以帮助我。非常感谢!!!
答案 0 :(得分:1)
当我使用你的模型时,我没有得到异常,但这并不重要,因为你无论如何都要做出一些改变。
首先,UserConfig
...
HasMany(x => x.Conversations).WithRequired(x => x.RecipientUser)
.HasForeignKey(x => x.SenderUserId);
......对我没有意义。这意味着对话属于收件人,而不属于发件人,这本身就有些意外。但是外键的名称是SenderUserId
。如果您将对象保存到此模型中,SenderUserId
将获得收件人ID
的值!
其次,假设前一个点是错误,那么通过定义......
会使它变得更加困难public User RecipientUser { get; set; }
public Guid SenderUserId { get; set; }
这意味着您只能通过Conversation
上的明确加入从User
导航到发件人SenderUserId
。相反,您只能通过设置RecipientUser
来设置收件人,而不是简单地设置外键值。
第三,SenderUserId
中不应该有Message
。它应该是ConversationId
。您可以通过其所属的Message
找到Conversation
的发件人。
总而言之,我将模型更改为此模型,将其简化为最低限度,并将int
用于ID
,因为它更容易阅读:
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; }
}
唯一的配置:
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);
}
}
(其中一个外键没有级联删除,因为这会导致SQL-Server错误:多个级联路径)。
一个简单的测试:
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();
}
结果:
用户:
ID Name
1 Recipient
2 Sender
Converstions:
ID RecipientUserID SenderUserID
11 1 2
消息:
ID Text ConversationID
21 a 11
22 b 11
答案 1 :(得分:0)
给定Conversation有1个用户外键列,它调用SenderUserId
// Here you set the user key for the old user!
conversation.RecipientUser = user;
// Here you are trying to change Conversation.SenderUserId from other user (currentUser)
currentUser.Conversations.Add(conversation);
如您所见,添加到收藏中的用户与您分配给对话1的内容不同.n无法以这种方式正常工作。
EF尝试用异常对你说,你试图添加/更改更多然后实体为releshinship一到零或一,错误消息有点雾我会说错误消息应该像&#34;一对多导航属性应该使用相同的实体&#34;
解决方案1)
// conversation.RecipientUser = user; remove this line why you need it?!
解决方案2)
在CurrentUser的对话框1中创建一个新属性,为User
创建另一个属性public class User
{
public User()
{
Conversations = new List<Conversation>();
CurrentUserConversations = new List<Conversation>();
}
public Guid Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
public string UserName { get; set; }
public ICollection<Conversation> Conversations { get; set; }
public ICollection<Conversation> CurrentUserConversations { get; set; }
}
public class Conversation
{
public Conversation()
{
Messages = new List<Message>();
}
public Guid ID { get; set; }
public User RecipientUser { get; set; }
public Guid SenderUserId { get; set; }
public User CurrentUser { get; set; }
public Guid? CurrentUserId { get; set; }
public ICollection<Message> Messages { get; set; }
}
public class UserConfig : EntityTypeConfiguration<User>
{
public UserConfig()
{
HasMany(x => x.Conversations).WithRequired(x => x.RecipientUser).HasForeignKey(x => x.SenderUserId);
HasMany(x => x.CurrentUserConversations).WithOptional(x => x.CurrentUser).HasForeignKey(x => x.CurrentUserId);
}
}
如何使用它:
var user = myDbContext.Users.First();
var currentUser = new User { Active = true, Id = Guid.NewGuid() };
myDbContext.Users.Add(currentUser);
var message = new Message { IsDelivered = true };
var conversation = new Conversation() { ID = Guid.NewGuid() };
conversation.Messages.Add(message);
conversation.CurrentUser = user;
currentUser.Conversations.Add(conversation);
myDbContext.Conversations.Add(conversation);
myDbContext.SaveChanges();