【问题标题】:Adding a foreign key to database - how does it change my application?向数据库添加外键 - 它如何更改我的应用程序?
【发布时间】:2017-01-06 14:39:32
【问题描述】:

我制作了一个工作应用程序,可以显示数据库中的联系人,允许编辑和删除他们以及他们的每个电子邮件/电话/标签。

数据库如下所示:

Contacts - Id (P), Name, Surname, Address;
Emails - EntryId (P), PersonId, Email1;
Telephones - EntryId (P), PersonId, Telephone1;
Tags - EntryId (P), PersonId, Tag1;

(其中 P 表示主键,PersonId 始终是联系人表中对应的 ID,即其电子邮件的人)

我没有以任何方式连接我的表,我只是通过这样的 id ID 处理了一个人的电子邮件,例如:

var mailsById = contactsData.Emails.Where(x => x.PersonId == ID).ToList();

现在我意识到我应该为表 Emails、Telephones、Tags 添加一个外键,这将是从表 Contacts 连接到 Id 的 PersonId。因此,我将其添加到电子邮件的表定义中:

CONSTRAINT [FK_Emails_Contacts] FOREIGN KEY ([PersonId]) REFERENCES [dbo].[Contacts] ([Id])

(与电话和标签相同)

一切顺利,在 EDMX 图表中,它现在显示联系人表和所有其他表(我想要的)之间的 (1,*) 连接,但现在我得到一个 500(内部服务器错误) 关于以下功能。函数返回有关数据库中所有联系人的完整信息(在前端,我有一个表 Name-Surname-Address-Emails-Telephones-Tags,这就是我将数据库中的所有表连接到一个列表的原因)。

public JsonResult getAll()
    {
        using (ContactsDBEntities contactsData = new ContactsDBEntities())
        {
            List<Contact_Info> completeList = new List<Contact_Info>();
            var contacts = contactsData.Contacts;
            var emails = contactsData.Emails;
            var telephones = contactsData.Telephones;
            var tags = contactsData.Tags;

            //GroupJoin:
            //Outer.GroupJoin(Inner, outer => key, inner => key, (outer, inner) => result)

            //first join joins contacts table with emails table
            var contactList = contacts.GroupJoin(emails,
                contact => contact.Id,
                email => email.PersonId,
                (contact, email) => new
                {
                    Id = contact.Id,
                    Name = contact.Name,
                    Surname = contact.Surname,
                    Address = contact.Address,
                    Email = email
                });

            //second join joins telephones to the existing contacts-emails list
            var contactList2 = contactList.GroupJoin(telephones,
                contact => contact.Id,
                telephone => telephone.PersonId,
                (contact, telephone) => new
                {
                    Id = contact.Id,
                    Name = contact.Name,
                    Surname = contact.Surname,
                    Address = contact.Address,
                    Email = contact.Email,
                    Telephone = telephone
                });

            //third join creates the needed contacts-emails-telephones-tags list
            var contactList3 = contactList2.GroupJoin(tags,
                contact => contact.Id,
                tag => tag.PersonId,
                (contact, tag) => new
                {
                    Id = contact.Id,
                    Name = contact.Name,
                    Surname = contact.Surname,
                    Address = contact.Address,
                    Email = contact.Email,
                    Telephone = contact.Telephone,
                    Tag = tag
                });

            //contactList3 to completeList
            foreach(var contact in contactList3)
            {
                Contact_Info temp = new Contact_Info();
                temp.Id = contact.Id;
                temp.Name = contact.Name;
                temp.Surname = contact.Surname;
                temp.Address = contact.Address;
                foreach (var em in contact.Email)
                {
                    temp.Emails.Add(em);
                }
                foreach (var tel in contact.Telephone)
                {
                    temp.Telephones.Add(tel);
                }
                foreach (var tag in contact.Tag)
                {
                    temp.Tags.Add(tag);
                }
                completeList.Add(temp);
            }

            return Json(completeList, JsonRequestBehavior.AllowGet);                
        }
    }

这是我在此函数中使用的 Contact_Info 类:

public class Contact_Info
    {
        public Contact_Info () {}

        public Contact_Info (string name, string surname, string address, List<Email> emails, List<Telephone> telephones, List<Tag> tags)
        {
            Name = name;
            Surname = surname;
            Address = address;
            Emails = emails;
            Telephones = telephones;
            Tags = tags;
        }

        public int Id;
        public string Name;
        public string Surname;
        public string Address;
        public List<Email> Emails = new List<Email>();
        public List<Telephone> Telephones = new List<Telephone>();
        public List<Tag> Tags = new List<Tag>();
    }

我尝试调试服务器端代码,它没有返回任何异常:/ 这是错误输出:ObjectContext 实例已被释放,不能再用于需要连接的操作。 p>

如果我更改了表的这个外键属性,你能告诉我我需要在工作应用程序中更改什么吗?现在这样做是否为时已晚(即是否需要从根本上更改我的代码),这里的外键约束有多重要?这是我第一次在更复杂的代码中使用数据库,所以如果我犯了一些请不要做的错误,请理解:)

非常感谢!

【问题讨论】:

  • 您在哪一行得到关于 ObjectContext 实例已被释放且不能再用于需要连接的操作的错误消息。?
  • @CodingYoshi 嗯,我找不到,是不是没有说明错误发生在哪一行?
  • 调试的时候,是在action方法结束前还是结束后报错?

标签: asp.net visual-studio foreign-keys


【解决方案1】:

如果您的实体之间存在导航属性(即您从数据库生成了 edmx 并且存在 FK 约束),那么您不需要单独获取实体然后加入它们。只需使用 Include():

var contacts = contactsData.Contacts
      .Include(x=>x.Emails)
      .Include(x=>x.Telephones)
      .Include(x=>x.Tags)
      .ToList();

我认为 Include 是 System.Data.Entity 命名空间的一部分。

【讨论】:

  • 我添加了 System.Data.Entity 命名空间并重写了我的 getAll() 函数,所以现在看起来像这样:public JsonResult getAll() { using (ContactsDBEntities contactsData = new ContactsDBEntities()) { var contacts = contactsData.Contacts .Include(x =&gt; x.Emails) .Include(x =&gt; x.Telephones) .Include(x =&gt; x.Tags) .ToList(); return Json(contacts, JsonRequestBehavior.AllowGet); } }
  • 它仍然返回一个错误,这次的输出是:在序列化'System.Data.Entity.DynamicProxies.Contact_55F0F20179BF8BAB1AC8CFFF6A7F318746B8C25429864C6FAE931BBF884EB6E3'类型的对象时检测到循环引用。
  • 所以您正在获取数据并进行序列化,但是父级有对子级的引用,而子级有对父级的引用。因此,当它序列化时,会有一个无穷无尽的循环引用。您需要做的是转到每个子模型并将 [JsonIgnore] 属性添加到指向父模型的导航属性。该属性位于 newtonsoft 命名空间中。这会让序列化器知道它不需要在子模型中再次序列化父级。如果从数据库重新生成模型,则需要再次添加属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
相关资源
最近更新 更多