正确创建实体数据模型

时间:2013-12-12 15:53:10

标签: c# entity-framework database-design

我对实体框架很陌生,并希望以最佳方式实现它。我想知道我的想法是否可以实施,以及它们是否是最佳实践。

模型1

我想在这里基本上使用Orders和Addresses实体来使用相同的查找表。查找表的想法是通过在查找实体中具有可以存储通用对象集合的属性来隐藏/显示特定用户的所有订单或所有地址。

Model 1 entity diagram

enter image description here

模型2

这与上面的原理非常相似,除了这是使用导航属性而不是标量属性。我认为这是正确的方法,但不确定是否存在我可能遇到的问题。

感谢您的帮助

Model 2 entity diagram

enter image description here

=======已添加16/12/2013 ==============

我希望通过为用户提供一些继承来进一步扩展此模型。基本上,目前有3种不同类型的用户拥有大部分属性,但将来他们可能会有一些特定的属性。为了帮助实现这一目标,我想出了下面的模型。

enter image description here

现在,当我尝试添加一名研究员时,它正确地抱怨

“INSERT语句与FOREIGN KEY约束”FK_HonoraryMemberLookup“冲突,我假设它意味着它正在尝试为其他两个用户类型添加查找,而不能因为空值而使用。

如何构建查找表以避免此错误?我应该为每种用户类型分别设置查找表吗?

再次感谢

2 个答案:

答案 0 :(得分:1)

您可能需要查看database normalization。规范化模型将有助于避免多次存储相同的数据(可能导致不一致)并降低复杂性。

您似乎只想将一组订单连接到用户,并将一组地址连接到用户。为此,我会使用Model 2之类的东西,但没有任何Lookup表(直接将地址和订单连接到用户表)。

您的Lookup表中唯一包含它的理由是IsPublic标志。它是干什么用的?如果Lookup是用户可以创建,保存并且通常都知道为thing的东西,则可能需要查找表,并且我将使用模型2.如果查找表仅存在以便于创建查询,我宁愿跳过它来保持数据库模型尽可能简单。

我自己没有处理过使用EF存储通用对象的问题,但这不是我之前看到过的任何关系数据库系统所做的事情,所以出于可移植性的原因我会谨慎使用它。

答案 1 :(得分:1)

我建议你使用Table-Per-Type继承来实现你想要做的事情。模型看起来像这样,Lookup实体标记为Abstract

TPT Diagram

以下是一些可能使用此模型的示例代码:

class Program
{
    static void Main(string[] args)
    {
        using (var container = new UserModelContainer())
        {
            var user = new User
                       {
                           FirstName = "Joe",
                           Surname = "Coder"
                       };

            var address = new Address
                          {
                              AddressLine1 = "123 Any Street",
                              AddressLine2 = "Apt 2A",
                              City = "Anytown",
                              StateProvince = "CA",
                              PostalCode = "12345",
                              Country = "United States",
                              IsPublic = false
                          };

            user.Lookups.Add(address);

            container.SaveChanges();
        }

        using (var container = new UserModelContainer())
        {
            foreach (var user in container.Users)
            {
                Console.WriteLine("Name: {0} {1}", user.FirstName, user.Surname);

                foreach (var address in user.Lookups.OfType<Address>())
                {
                    Console.WriteLine(address.AddressLine1);
                    Console.WriteLine(address.AddressLine2);
                    Console.WriteLine(address.City);
                    Console.WriteLine(address.StateProvince);
                    Console.WriteLine(address.PostalCode);
                    Console.WriteLine(address.Country);
                    Console.WriteLine("Address is {0}", address.IsPublic ? "Public" : "Private");
                }
            }
        }
    }
}