实体框架代码优先和链接的实体

时间:2018-08-03 14:15:42

标签: c# entity-framework foreign-keys

我有AspNetUser实体:

public partial class AspNetUser
{
    public string Id { get; set; }

    [Required]
    [StringLength(256)]
    [Index(IsClustered = false, IsUnique = true)]
    public string UserName { get; set; }
    ....

接口:

public interface IProfile
{
    string FirstName { get; set; }
    string LastName { get; set; }
    string Nickname { get; set; }
}

public interface IMembershipEntity
{
    string AspNetUserId { get; set; }
    AspNetUser AspNetUser { get; set; }
}

还有2个实体,它们每个都以FK链接到AspNetUser(都实现IProfile和IMembershipEntity):

public partial class Driver : IMembershipEntity, IProfile
{

    #region IProfile
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    #endregion

    #region IMembershipEntity
    public string AspNetUserId { get; set; }
    [ForeignKey("AspNetUserId")]
    public virtual AspNetUser AspNetUser { get; set; }
    #endregion

   ... driver fields


public class User : BaseEntity, IMembershipEntity, IProfile
{
    #region IMembershipEntity
    public string AspNetUserId { get; set; }
    public virtual AspNetUser AspNetUser { get; set; }
    #endregion

    #region IProfile
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    #endregion

    .... user fields
}

现在我需要一个需要从AspNetUser获取FirstName / LastName的方法,像这样:

        var element = (from i in db.AspNetUsers
                    select new UserElementDomain()
                    {
                        UserId = i.Id,
                        CompanyName = i.Company.Name,
                        FirstName = (get FirstName here),
                        LastName = (get LastName here),
                        RoleName = i.AspNetRoles.FirstOrDefault().Name,
                        SMSnumber = i.SMSnumber,
                        UserName = i.UserName,
                        .....
                    }).FirstOrDefault();

该怎么做? 我可以向AspNetUser添加2个属性,例如:

    public virtual User User { get; set; }
    public virtual Driver Driver { get; set; }

但是怎么说,它应该是一个或零个链接,而不创建UserId / DriverId

即使有它,我也必须编写如下代码:

FirstName = (i.User!=null)? i.User.FirstName : ((i.Driver!=null)?i.Driver.FirstName : String.Empty)

并且我不喜欢这段代码,因为当我再添加一个实体时,我必须查看所有代码并再添加一个条件。如何正确做?可能是使用接口/继承吗?

1 个答案:

答案 0 :(得分:0)

我以前看过重复的代码,但是很少看到重复的数据结构。

根据您当前的代码,如果User.FirstName =“ A”&Driver.FirstName =“ B”,则结果仅为“ A”。如果您有一个名为“ Employee”的新实体,并且您不使用当前样式对它进行硬编码,谁知道哪个名称将是3个实体中的真实名字?

您当前的代码可以简化为:

i.User?.FirstName ?? i.Driver?.FirstName ?? i.Whatever?.FirstName ?? String.Empty

但这是您要管理的真实数据吗?

我给您另外两个选择:

  1. 向根实体添加属性,在您的情况下为AspNetUser:

    public class AspNetUser
    {
    ....
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    ....
    }
    
  2. 管理1个实体中的常用配置文件

    public class AspNetUser
    {
    ....
    public virtual AspNetUserProfile AspNetUserProfile { get; set; }
    }
    public class AspNetUserProfile
    {
    [Key]
    public string Id { get; set; }
    
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    ....
    [ForeignKey("Id")]
    public virtual AspNetUser AspNetUser { get; set; }
    }
    

然后在您的代码中:

   db.AspNetUsers.Select(i => new UserElementDomain()
                {
                    UserId = i.Id,
                    CompanyName = i.Company.Name,
                    FirstName = i.AspNetUserProfile?.FirstName,
                    LastName = i.AspNetUserProfile?.LastName,
                    RoleName = i.AspNetRoles.FirstOrDefault().Name,
                    SMSnumber = i.SMSnumber,
                    UserName = i.UserName,
                    .....
                })

如果驱动程序/用户/ Empolyee要获取名字,只需使用:

Empolyee.AspNetUser.AspNetUserProfile?.FirstName