【问题标题】:Can I get EntityFramework 4.1 to return queries that return results that consider data in both the DbSet.Local and database?我可以让 EntityFramework 4.1 返回查询结果,这些查询返回考虑 DbSet.Local 和数据库中的数据的结果吗?
【发布时间】:2011-06-20 00:55:35
【问题描述】:

假设我在一个名为 TestDB 的数据库中有一个表,其中一个名为 Table1 的表包含两列

ID
Name

在这张表中,有两行,

ID 1 and Name 'Row1'
ID 2 and Name 'Row2'

如果这是我的代码

var currObj = Table1.Where(o => o.Name.Contains("Row1")).FirstOrDefault();
currObj.Name = "Row1a";

var a = Table1.Where(o => o.Name.Contains("Row1a")).FirstOrDefault();
var b = Table1.Local.Where(o => o.Name.Contains("Row1a")).FirstOrDefault();

a 将返回 null,而 b 将返回一个值。

如果我这样做

var c = Table1.Where(o => o.Name.Contains("Row2")).FirstOrDefault();
var d = Table1.Local.Where(o => o.Name.Contains("Row2")).FirstOrDefault();

然后 c 会返回一些东西,但 d 不会。

对我来说,这似乎不直观,因为数据可能存在两个不同的位置。对于我所做的每个查询,我都必须查看数据库和 Local 对象并将它们合并在一起。就像它在本地对象中发生变化一样,我必须考虑到这一点。 Entity Framework 是否有任何机制可以同时考虑数据库中的数据和本地数据?

如果我去了

var e =  Table1.AMagicSolution.Where(o => o.Name.Contains("Row1a")).FirstOrDefault();
var f = Table1.AMagicSolution.Where(o => o.Name.Contains("Row2")).FirstOrDefault();

那么 e 和 f 都会返回一些东西(f 来自数据库,e 来自 Local 对象)

【问题讨论】:

    标签: entity-framework c#-4.0 .net-4.0 entity-framework-4.1


    【解决方案1】:

    你的期望有点奇怪。 EF 上下文就像一个工作单元 = 它用于处理单个逻辑事务,因此您应该尝试以它知道记录是否在本地存储中的方式设计您的应用程序。

    如果由于任何原因您的应用程序不知道记录是否在本地存储中,您应该始终将查询与本地存储和数据库分开!原因是性能和不必要的数据库往返。使用以下示例中的帮助器首先查询本地存储,并且仅当本地存储中不存在记录时才查询数据库:

    public static Table1 AMagicSolution(this IQueryable<Table1> query, string name)
    {
        var item = Table1.Local.Where(t => t.Name.Contains(name)).FirstOrDefault(); 
        if (item != null)
        {
            item = Table1.Where(t => t.Name.Contains(name)).FirstOrDefault();
        }
    
        return item;
    } 
    

    【讨论】:

    • 谢谢,这比其他解决方案好一点,尽管此时性能对我来说不是问题。关于这个解决方案,我唯一想说的是,我希望它更通用。我需要为每个查询的每个类编写一个特定的方法。如果您可以只传递一个 DbSet 作为表以及您希望在其上作为函数运行的 linq 查询,那就太好了。但我玩过它,可悲的是,我认为这是不可能的。
    • 我猜上面的代码应该是:if (item == null) 而不是 if (item !=null)
    【解决方案2】:

    与您的其他问题没有太大区别。

    Table1.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Unchanged)
        .Where(o => o.GetType() == typeof(Table1Type) 
               && o => o.Name.Contains("Row1a"))
        .FirstOrDefault();
    

    来自docs:“EntityState 是一个位字段,因此可以通过对多个 EntityState 值进行按位 OR 在一次调用中检索多个状态的状态条目。”

    【讨论】:

    • mmm 目前无法对此进行测试,将在我重新进入时进行测试。如果我还将 EntityState.Modified 添加到此,我将获得更改后的行的哪一行?它会获取数据库中的原始数据还是更改后的数据?
    • 你会得到修改后的未保存值。
    • 不幸的是,我的 Entities 类现在是一个 DbContext,所以我无法运行它,我想我可能可以使用 ChangeTracker 来实现相同类型的东西。
    猜你喜欢
    • 2012-10-21
    • 1970-01-01
    • 2022-01-23
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    相关资源
    最近更新 更多