8

我有一个用户可以有多个地址的情况。因此,我的用户类上有一个 ICollection。但我也希望用户能够选择默认地址。所以我做了以下事情:

public class User 
{
    public int Id { get; set; }
    public int? DefaultAddressId { get; set; }
    [ForeignKey("DefaultAddressId")]
    public virtual Address DefaultAddress { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
    //properties were removed for purpose of this post
}

我想public virtual Address DefaultAddress { get; set; }完全删除,保留 DefaultAddressId 并使用 Fluent API 映射它,因为当前的设置会造成很多麻烦(在这个类和我有类似设置的其他类中)。那么这可以使用fluent api来完成吗?

更新: 地址类目前没有对用户类的任何引用,它是一种单向关系。但是,是的,一个地址只属于一个用户,它不是多对多的关系。这是地址类:

public class Address
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Details { get; set; }
    public virtual Area Area { get; set; }
}
4

4 回答 4

10

我会亲自将外键关系从Userto移动,并在地址类上Address添加一个属性。IsDefaultAddress

public class Address
{
    public int Id { get; set; }

    // This property marks the FK relation
    public virtual User User { get; set; }

    public string Name { get; set; }
    public string Details { get; set; }
    public virtual Area Area { get; set; }

    // This property signals whether this is the user's default address
    public bool IsDefaultAddress { get; set; }
}

EF 会知道它需要和之间的Foreign Key关系。AddressUser

这将大大简化您的模型。也就是说,当然,如果一个地址只能属于一个用户(正如 Slauma 在评论中所问的那样)。

于 2011-03-30T19:39:55.633 回答
8

您在问题中的原始模型应该可以工作。你可以很容易地测试它:

  • 创建新的控制台应用程序(VS 2010)
  • 将其命名为“EFTestApp”
  • 添加对“EntityFramework.dll”的引用
  • 删除 Program.cs 的内容并将以下代码复制到文件中

程序.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace EFTestApp
{
    public class User
    {
        public int Id { get; set; }
        public int? DefaultAddressId { get; set; }
        [ForeignKey("DefaultAddressId")]
        public virtual Address DefaultAddress { get; set; }
        public virtual ICollection<Address> Addresses { get; set; }
    }

    public class Address
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Address> Addresses { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new Context())
            {
                try
                {
                    User user = new User() { Addresses = new List<Address>() };

                    Address address1 = new Address() { Name = "Address1" };
                    Address address2 = new Address() { Name = "Address2" };

                    user.Addresses.Add(address1);
                    user.Addresses.Add(address2);

                    context.Users.Add(user);

                    context.SaveChanges();
                    // user has now 2 addresses in the DB and no DefaultAddress

                    user.DefaultAddress = address1;
                    context.SaveChanges();
                    // user has now address1 as DefaultAddress

                    user.DefaultAddress = address2;
                    context.SaveChanges();
                    // user has now address2 as DefaultAddress

                    user.DefaultAddress = null;
                    context.SaveChanges();
                    // user has now no DefaultAddress again
                }
                catch (Exception e)
                {
                    throw;
                }
            }
        }
    }
}

在 SQL Server Express 中,它创建了一个名为“EFTestApp.Context”的新数据库。您可以在上面的每个 SaveChanges 上设置断点,跨步并观察数据库中的更改。

如果您查看数据库中的关系,那么有两个,并且在Addresses数据库中的表中是一个外键列User_Id

我认为您也可以删除public int? DefaultAddressId { get; set; }and [ForeignKey("DefaultAddressId")]。它使用可选的 DefaultAddress 创建相同的数据库表和关系。

也许您希望Address -> User根据需要建立关系(地址不能在没有用户的情况下单独存在于数据库中)。然后您可以将其添加到 Context 类中:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
                .HasMany(u => u.Addresses)
                .WithRequired();
}

它使User_IdAddresses 表中的表不可为空,并默认设置级联删除。因此,当用户被删除时,其所有地址也会被删除。

于 2011-03-31T00:08:44.327 回答
2

DefaultAddressId不需要任何特定的映射,因为它只是表中的列,与User表没有任何关系(FK)Address。不会创建任何关系,因为导航属性在任何一侧都不存在。它也应该是一对一的关系,因为 EF 不支持唯一键,所以它不起作用。

我喜欢@Sergi Papaseit 提供的解决方案

于 2011-03-30T19:42:34.850 回答
0

如果要删除 DefaultAddress 属性,则不需要映射它。您可以在那里拥有该属性,并且 EF 应该知道如何映射它,前提是 DefaultAddressId 在 User 表中

于 2011-03-30T17:34:03.590 回答