如何阻止EntityFramework获取所有行

时间:2013-11-21 10:40:02

标签: c# .net sql entity-framework

我尝试为EntityFramework创建一个通用的CreateOrUpdate函数,其中我的类/表总是有一个ID字段。由于该数据被发送到网页并发回服务器,因此我完全与上下文断开连接,并且必须使用标准(set.Any / set.FirstOrDefault)检查方式来查看我的对象是否已存在。

该方法在完成工作和根据需要创建/更新方面非常有效。但我发现db.Set<T>().FirstOrDefault(whereFunction);从数据库中收回所有数据,然后在内存中执行FirstOrDefault。我更喜欢在SQL中发生这种情况,但无论我尝试过什么,我都无法让它发挥作用。

对于如何将FirstOrDefault函数转换为正确的SQL以便我不从DB中检索太多,您有什么建议吗?

另外,我尝试了FirstAny&amp; Count,所有这些都从DB中获取所有行。

public void CreateOrUpdateEntity<T>(T entity) where T : class
{
    using (var db = new ProjectContext())
    {
        Func<T, bool> whereFunction = m => m.As<dynamic>().ID == entity.As<dynamic>().ID;
        var firstValue = db.Set<T>().FirstOrDefault(whereFunction);

        if (firstValue == null)
        {
            db.Set<T>().Attach(entity);
            db.ChangeTracker.Entries<T>().First(e => e.Entity == entity).State = EntityState.Added;
        }
        else
        {
            db.ChangeTracker.Entries<T>().First(e => e.Entity == entity).State = EntityState.Modified;
        }
    }
}

1 个答案:

答案 0 :(得分:4)

您应该使用表达式而不是Func<T, bool>委托。委托的使用调用在内存中执行的Enumerable.FirstOrDefault(Func<T,TResult>)方法(并且需要加载到客户端的所有数据),而不是Queryable.FirstOrDefault(Expression<Func<T, TResult>>),它被翻译成SQL并在服务器端执行。

注意:我怀疑你的代表是否可以翻译成SQL。

BTW:为了按身份获取实体,您可以使用方法Find

var firstValue = db.Set<T>().Find(entity.As<dynamic>().ID);