实体框架包括财产

时间:2013-09-03 10:03:16

标签: c# linq entity-framework include linq-to-entities

最初,我有一个基本的Client只包含:

public class Client : Entity
{
    [Required]
    public string Name { get; set; }
}

我的User以及通常的Name字段等都有Client

public class User : Entity
{
    [Required, MinLength(4), Display(Name = "Username")]
    public string Username { get; set; }
    [Required, MinLength(2), Display(Name = "First Name")]
    public string FirstName { get; set; }
    [Required, MinLength(2), Display(Name = "Last Name")]
    public string LastName { get; set; }
    [Required, EmailAddress]
    public string Email { get; set; }
    ...
    [Required]
    public virtual Client Client { get; set; }
}

我的Get方法:

public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string[] includeProperties = null)
    {
        IQueryable<TEntity> query = dbSet;

        if (includeProperties != null)
            query = includeProperties.Aggregate(query, (q, s) => q.Include(s));

        query = query.Where(x => !x.Deleted);

        if (filter != null)
            query = query.Where(filter);

        return orderBy != null ? orderBy(query).ToList() : query.ToList();
    }

这一切都很好。所以,关于问题:它实际上是我的客户端,因为为AccountManager添加了一个额外的属性(即User),它不喜欢我。

public class Client : Entity
{
    [Required]
    public string Name { get; set; }

    [Required]
    public CompanyType CompanyType { get; set; }

    [Required]
    public ClientStatus Status { get; set; }

    [SomethingInHere?]
    public virtual User AccountManager { get; set; }

    public DateTime? AccessFrom { get; set; }
    public DateTime? AccessTo { get; set; }

    public DateTime? ClosedDate { get; set; }
}

我已将“AccountManager”添加到INCLUDE_STRING的{​​{1}},甚至最近尝试使用各种Get / ForeignKey数据注释但无法获取随身携带AccountManager Required

有了这个,我认为它是其中的一部分,如果不是我完全不再提出任何User的全部原因。

简而言之,我对EF关系处理的掌握有限,而且今天我的谷歌搜索能力似乎还没有达到标准。

许多UserUser。每个Client一个UserAccountManager。为什么这对我这么难?

编辑:圆形答案。

在模型构建器部件中添加:

Client

并修改了modelBuilder.Entity<User>() .HasRequired(x => x.Client) .WithMany(x => x.Users); modelBuilder.Entity<Client>() .HasOptional(x => x.AccountManager); 以包含用户列表:

Client

这让EF非常高兴能够把它全部搞定。

2 个答案:

答案 0 :(得分:1)

问题可能是Code-First约定没有做你真正想要的正确的事情。添加AccountManager属性后,实体框架约定正在检测一对两个引用导航属性,即User.ClientClient.AccountManager。 EF假定它们是同一单一关系的导航端,然后必须是一对一的关系,因为属性是引用而不是集合。

但是你说你真的想要:“许多用户到客户端。一个用户作为每个客户的AccountManager”。这些是两个关系而不仅仅是一个,即两个引用中的每一个属于另一个关系。要实现此目的,您必须使用Fluent API显式覆盖约定:

modelBuilder.Entity<User>()
    .HasRequired(u => u.Client)
    .WithMany();

modelBuilder.Entity<Client>()
    .HasOptional(c => c.AccountManager)
    .WithMany();

答案 1 :(得分:0)

这可能有资格作为评论的更多内容,但不适合那里......

  1. 将所有自定义内容放在一边,并尝试按预期直接查询EF。这至少会排除您自己的代码与实体设置方式之间的任何问题(现在很难说清楚,因为我们无法看到这个有限的代码示例可能出现问题的地方)。
  2. 使用Include的更好方式(IMO)是使用强类型版本:query.Include(u => u.Client)。使您的代码不易出现运行时错误。
  3. 显示无法恢复相关属性的查询,并发布所有相关实体/属性。您是否包含与EF约定匹配的外键ID属性?这是使用EF Code First还是EDMX模型?
  4. 编辑 - This link可以帮助您建立关系。我也注意到您的User实体缺少ClientId属性(并且Client缺少AccountManagerId)。为了提取“导航属性”(您可能希望包含在Google搜索中的术语,如果您还没有),则需要知道要加入的外键属性。