标签: navigational-properties

编写LINQ查询.加入VS导航属性

我正在尝试更多地了解Linq查询和实体框架(4.1).请查看以下两个查询.两个查询都返回汽车类型名称(CarType.Name)

在第一个查询中,我使用了join并忽略了导航属性CarType

from c in Cars.AsEnumerable().
Where(e => e.CarId == Guid.Parse("0501cc96-5610-465d-bafc-16b30890c224"))
join ct in CarTypes on c.CarTypeId equals ct.CarTypeId
select new CarType {
    Name = ct.Name
}
Run Code Online (Sandbox Code Playgroud)

第二,我使用了导航属性CarType

from c in Cars.AsEnumerable()
where c.CarId == Guid.Parse("0501cc96-5610-465d-bafc-16b30890c224")
select new CarType {
    Name = c.CarType.Name
}
Run Code Online (Sandbox Code Playgroud)

我在LinqPad中运行了两个,因此有Guid.Parse函数.

当我运行这些时,第一个语句运行得更快.LinqPad报告00:00:036.第二个语句运行较慢,LinqPad报告00:00:103

看看结果似乎Linq查询使用连接而不是导航属性更快.真的是这样吗?请有人对此表示赞赏.在编写Linq查询时,是否有任何一般指导,我应该遵循的最佳实践?

谢谢

linq optimization navigational-properties entity-framework-4.1

8
推荐指数
1
解决办法
1852
查看次数

基于抽象实体的急切加载嵌套导航问题(EF CTP5)

我的EF模型的一部分看起来像这样:

在此输入图像描述

摘要:

  • 位置有很多帖子
  • Post是一个抽象
  • 讨论得出帖子
  • 讨论有很多评论

现在,我正试图实现的查询:

获取有关位置ID 1234的信息,包括与这些讨论相关的任何讨论和评论.

我可以得到讨论和这样的评论:

var discussions = ctx.Posts
                     .OfType<Discussion>()
                     .Include(x => x.Comments)
                     .ToList();
Run Code Online (Sandbox Code Playgroud)

但我似乎无法根据位置实体上的帖子导航获取它.

我试过这个:

var locationWithDiscussionsAndComments = ctx
                    .Locations
                    .Include(x => x.Posts
                                   .OfType<Discussion>()
                                   .Select(y => y.Comments))
                    .SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

哪个编译,但我得到错误:

System.ArgumentException:包含路径表达式必须引用实体定义的属性,也可以引用嵌套属性或对Select的调用.参数名称:路径

有任何想法吗?我可能会从帖子中"倒退":

var locationWithDiscussionsAndComments = ctx
                   .Posts
                   .Include(x => x.Location)
                   .OfType<Discussion>()
                   .Include(x => x.Comments)
                   .Where(x => x.LocationId == 1234)
                   .Select(x => x.Location)
                   .ToList();
Run Code Online (Sandbox Code Playgroud)

但就我的存储库而言,这在毛发和语义上都是错误的(我不应该通过帖子库来获取有关位置的信息).

有任何想法吗?

编辑

因此,在对它进行更大的思考之后,我意识到这OfType<T>是一个过滤操作.据我们所知,EF不支持使用预先加载进行过滤.唯一的选择是检索所有内容,或使用匿名类型投影.

我无法检索所有内容,因为涉及的元数据太多了.所以我正在尝试匿名类型投影.

c# abstract-class eager-loading navigational-properties entity-framework-ctp5

5
推荐指数
1
解决办法
4372
查看次数

如何在不丢失导航属性的情况下回滚实体删除

我们正在使用实体框架代码优先,我遇到了在我们不希望的情况下尝试回滚插入,更新和删除实体更改的问题SaveChanges().

具体来说,我有一个datagridview,我用它作为TableEditor,来更改一些辅助表.datagridview绑定到DbSet<TEntity>.

我的回滚更新似乎工作正常,我只是将currentValues设置回其OriginalValues,并将状态更改为unchanged.

当一个记录插入到gridview中(但没有保存更改)时,它永远不会出现在实体类中,我再也看不到了......所以我猜它不会进入dbSet,也没有回滚是需要这个吗?

但我的主要问题在于删除:

根据我的理解,当记录被"删除"(例如tableData.Remove(currentItem);)时,它被简单标记为删除,直到调用SaveChanges.因此,如果我将状态从deleted返回更改为unchanged,那应该处理回滚,对吧?

那么,记录确实再次显示,但记录的导航属性已经消失!(即包含外键的列和与其他实体的必需关系).为什么是这样??!

这是我到目前为止:

    public void RollbackChanges(DbEntityEntry entry)
    {
        if (entry.State == EntityState.Modified)
        {
            foreach (var propertyName in entry.OriginalValues.PropertyNames)
            {
                entry.CurrentValues[propertyName] = entry.OriginalValues[propertyName];
            }
            entry.State = EntityState.Unchanged;
        }
        else if (entry.State == EntityState.Deleted)
        {
            entry.State = EntityState.Unchanged;
        }
        else if ((entry.State == EntityState.Added) || (entry.State == EntityState.Detached))
        {
            MessageBox.Show("I don't think this ever happens?");
        }
    }
Run Code Online (Sandbox Code Playgroud)

用法示例:

    foreach (var entity …
Run Code Online (Sandbox Code Playgroud)

.net entity-framework code-first navigational-properties

5
推荐指数
1
解决办法
817
查看次数

在实体上显式加载多个引用/集合

考虑以下实体模型:

public class Parent
{
    public virtual FirstChild FirstChild { get; set; }
    public virtual SecondChild SecondChild { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在我的代码中,我加载了Parent实体:

Parent parent = <loaded in some way>;
Run Code Online (Sandbox Code Playgroud)

要显式加载其导航属性,我使用

db.Entry(parent).Reference(p => p.FirstChild).Load();
db.Entry(parent).Reference(p => p.SecondChild).Load();
Run Code Online (Sandbox Code Playgroud)

但这会导致两个数据库查询。

问题:有没有更优雅的方式,允许在单个查询中显式加载多个导航属性?

如果我没有parent加载,我会立即加载:

Parent parent = db.Parents
    .Include(p => p.FirstChild)
    .Include(p => p.SecondChild)
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

但是,正如我所提到的,我已经在没有相关实体的情况下加载了它(并且我无法修改加载代码)。

c# entity-framework eager-loading navigational-properties

5
推荐指数
1
解决办法
1737
查看次数