实体框架并不总是包括子实体

时间:2013-06-05 15:59:55

标签: c# entity-framework entity

我有User分配给Client。在拉出User对象时,我将Client对象作为其中的一部分。简单。

这在登录时可以正常工作。无论我以谁登录,User对象都有Client

但是,使用完全相同的方法来获取User和登录时一样,要通过管理菜单进行编辑,Client有时会null }。

我说有时候

1)在Firefox中 - 当试图查看大多数但不是所有用户(和我自己)的详细信息时,Client附带的User将是null。由于实际存在Users,因此只能查看Client中的几个。

2)在Chrome中 - 所有用户(除我自己)都可见。只有在尝试查看自己的用户时,Client才会null

我不明白;两个浏览器只是转到相同的网址,即/Users/EditGet/28,甚至使用两种不同的方法(GetByIdGetByUserName),它提供了相同的结果 - 尽管两者都使用了基本的Get功能:

编辑:BaseService类,而不是编辑。

internal CustomContext context;
internal DbSet<TEntity> dbSet;

public BaseService(CustomContext context)
{
    this.context = context;
    this.dbSet = context.Set<TEntity>();
}

public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    string includeProperties = "")
{
    IQueryable<TEntity> query = dbSet.Where(e => !e.Deleted);

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

    foreach (var includeProperty in includeProperties.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries))
    {
        query = query.Include(includeProperty);
    }

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

我不确定为什么浏览器的选择会影响后端查询的结果。当然,无论我使用什么浏览器,都应该使用Client返回User

我假设可能是基本Get方法的基本错误,但它没有解释我所看到的行为...

如果有人能够对此有所了解,我将非常感激。

编辑2: CustomContext:

public class CustomContext : DbContext, ICustomContext
{
    public IDbSet<User> Users { get; set; }
    public IDbSet<Client> Clients { get; set; }
}

2 个答案:

答案 0 :(得分:0)

您可能还想更改逗号分隔的包含列表 - 这可能容易出现格式错误;你可以把它改成param或像这样的数组:

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

            var query = ((DbQuery<TEntity>)dbset);

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

            query = query.Where(e => !e.IsDeleted);


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

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

我认为如果它依赖于浏览器,就像你说的那样可能会出现一些字符串格式问题...无论如何都值得一试。

编辑:将查询更改回DbQuery

EDIT2 :修复是在Include之前调用Where,因为必须在Include或{{1}上调用DbSet }}。它似乎是随机的原因是,当没有过滤器时,然后在DbSet / DbQuery上调用包含它们应该在的位置。

由于代码调用DbQuery而不容易发现......这不是开箱即用的标准。 IQueryable<T>.Include位于DbSet或DbQuery上。

答案 1 :(得分:0)

我认为问题源于我们存储当前登录的User的方式。

当尝试检索另一个同一User个对象时,它会失败并同时取出Client

仍然不太清楚为什么会这样。我有一些提示,它与Object State Manager和跟踪多个对象有关 - 尽管当前登录的User对象实际上并未从数据库中提取...

解决这个问题的方法是做一个简单的检查,看看User拉出的内容是否与当前登录的User相同,如果问题存在({{ 1}}是Client)然后拉出null并将其附加到Client对象。

User

粗俗,并且关于如何正确解决这个问题的答案还不是很好,但它确实有效,并且所有private User GetUser(long id) { var user = Services.UserService.GetById(id); if (user.Client == null && CurrentUser.Id == user.Id) user.Client = Services.ClientService.GetByClient(CurrentUser.Client); return user; } 都可以再次完全编辑。