【问题标题】:Iteration error in Entity Framework实体框架中的迭代错误
【发布时间】:2017-08-27 18:33:05
【问题描述】:

我正在使用 C# Winforms 创建一个简单的消息传递应用程序。我正在连接到在我的计算机上运行的 SQLEXPRESS 服务器并将所有内容存储在那里。

这是我的架构:

public class UserContext : DbContext {
    public UserContext() : base("name=BuddyDatabase") {

    }
    public DbSet<User> Users { get; set; }
    public DbSet<Message> Messages { get; set; }
}

public class User {
    [Key]
    public string username { get; set; }
    public string password { get; set; }

    public static implicit operator User(bool v) {
        throw new NotImplementedException();
    }

    public virtual List<User> friends { get; set; }
}

public class Message {
    [Key]
    public int ID { get; set; }

    public virtual User sender { get; set; }
    public virtual User recipient { get; set; }

    public string content { get; set; }

    public virtual List<User> group { get; set; }
}

很简单

向单个收件人发送消息有效,但群组消息无效,每当我打开“消息屏幕”时,我都会收到此错误:

无法创建“WindowsFormsApp1.User”类型的常量值。此上下文仅支持原始类型或枚举类型。

这是我在消息屏幕加载时运行的方法:

var x = db.Messages.Where(b => b.recipient.username == currentuser.username);
foreach (var y in x) {
    MainMessagesBox.Text += y.content;
}
x = null;

var z = db.Messages.Where(b => b.group.Contains(currentuser));
foreach (var y in z) {
    MainMessagesBox.Text += y.content;
}

(Visual Studio 突出显示此行中的“in”作为错误原因。)

foreach (var y in z) {

认为这可能是我使用 Where 方法并涉及非基元(如错误消息所示)的问题,因此我尝试更改我的架构,以便该组是包含预期收件人的用户名的字符串列表和相应地修改了方法,但这也不起作用。将根据要求提供该试验的代码和错误。

这是实际的“发送消息”代码:

if (!textBox1.Text.Contains(',')) {
    db.Messages.Add(new Message { sender = currentuser, recipient = db.Users.Find(textBox1.Text), content = currentuser.username + ": " + ContentBox.Text + "\n" });
    db.SaveChanges();
} else {
     List<User> recips = new List<User>();
     string[] poop = textBox1.Text.Split(',');

     foreach (var x in poop) {
         recips.Add(db.Users.Find(x));
     }

     db.Messages.Add(new Message { sender = currentuser, group = recips, content = ContentBox.Text });
     db.SaveChanges();
}

poop 是一个由文本框中的逗号分隔的预期收件人数组,这是临时的。

抱歉,如果有任何格式错误或我不清楚,这是我的第一个问题。

提前谢谢你。

【问题讨论】:

  • 您应该在 Messages 表中为“sender”和“recipient”定义一个外键 - ref msdn.microsoft.com/en-us/library/jj713564(v=vs.113).aspx
  • 如果我理解正确,一条消息要么发送给单个收件人,要么发送给一个组。但是你不应该在你的数据库中区别对待它。一封邮件要么在收件人列表中有多个收件人,要么只有一个。

标签: c# sql .net winforms entity-framework


【解决方案1】:

问题是对消息表的 Select 查询,您可以在其中检查当前用户是否在 group 列表中。这是行不通的,因为查询必须转换为 SQL 才能发送到数据库。

SQL 不了解“用户”类型是什么,也无法比较引用。实际上,C# 也没有正确比较这一点。在您的情况下,具有相同username 的两个“用户”类型的对象将不相等。您需要比较这些对象的用户名。

无论如何,正如 Bitmask 在评论中解释的那样,您必须正确定义消息的外键。

消息的发送者很容易。你的User 类中有一个public virtual ICollection&lt;Message&gt; Messages { get; set; }

但是对于收件人来说,这是一个多对多的关系。所以User 类和Message 类都分别有一个MessageUser 的集合。

这样的事情应该可以工作:

public class User {
    [Key]
    public string username { get; set; }
    public string password { get; set; }

    public static implicit operator User(bool v) {
        throw new NotImplementedException();
    }

    public virtual ICollection<Message> SentMessages { get; set; }
    public virtual ICollection<Message> ReceivedMessages { get; set; }

    public virtual List<User> friends { get; set; }
}

public class Message {
    [Key]
    public int ID { get; set; }

    public virtual User Sender { get; set; }
    public virtual ICollection<User> Recipients { get; set; }

    public string content { get; set; }
}

查看this link 以获取有关如何使用数据注释或流式 API 定义多对多关系的示例。这假设您使用的是 EF6。如果您使用的是旧版本的 EF,您可能必须自己定义连接表才能获得多对多关系。

关于查询。您可以在消息屏幕的 OnLoad 方法中使用以下内容:

MainMessagesBox.Text = string.Join(System.Environment.NewLine, currentuser.ReceivedMessages.Select(m => m.content))

这将连接所有消息,用新行分隔。

【讨论】:

  • 我实现了你给我的模式,我现在正试图让一切顺利,但我无法删除我的任何一个表中的任何行。我在尝试删除任何内容时遇到外键约束错误。这可能是一个菜鸟错误,但请帮忙。
猜你喜欢
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-05
  • 2015-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多