繁体   English   中英

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

[英]Entity Framework not always including child entities

我有一个User分配给一个Client 拔出User对象时,我将Client对象作为它的一部分。 简单。

这在登录时应能正常工作。无论我以谁身份登录, User对象都有一个Client

然而,使用完全相同的方法来获取User登录时,通过管理菜单进行编辑的,在Client有时是null

有时说:

1)在Firefox中-尝试查看大多数 (但不是全部)用户(和本人)的详细信息时,附加到UserClientnull 由于Client实际存在,因此只能看到几个Users

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

我不明白 两种浏览器都直接使用相同的URL,即/Users/EditGet/28 ,甚至使用两种不同的方法( GetByIdGetByUserName ),它也提供相同的结果-尽管可以GetById ,两者都使用了基本的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();
}

我不确定为什么选择浏览器会完全影响后端查询的结果。 无论我使用哪种浏览器,它肯定都应该与User一起返回Client

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

如果有人能对此有所启示,我将不胜感激。

编辑2:CustomContext:

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

您可能还想从逗号分隔的包含列表中更改-可能易于格式化错误; 您可以将其更改为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 :修复方法是Where必须在DbSetDbQuery上调用Where Include之前,先将对Include调用。 看起来随机的原因是,当没有过滤器时,包含被调用在DbSet / DbQuery上应该位于的位置。

不容易发现,因为代码已调用IQueryable<T>.Include ...,这不是开箱即用的标准功能。 Include在DbSet或DbQuery上。

我看来,问题出在我们存储当前登录的User

当尝试检索同一User对象中的另一个对象时,它随后也无法拉出Client

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

但是,解决此问题的方法是进行简单检查,以查看是否拉出的User与当前登录的User相同,并且是否存在问题( Clientnull ),然后拉出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;
}

关于如何正确解决此问题,这还很粗略,远未达到一个合理的答案,但它确实有效,并且所有User都可以再次完全编辑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM