我试图为EntityFramework创建一个通用的CreateOrUpdate函数,其中我的类/表总是有一个ID字段。由于该数据发送到网页并回发到服务器,我完全与上下文断开连接,并且必须使用标准(set.Any/set.FirstOrDefault)方法来检查我的对象是否已经存在。如何阻止EntityFramework获取所有行
该方法在完成工作和根据需要创建/更新方面完美工作。但我发现的是db.Set<T>().FirstOrDefault(whereFunction);
从DB中取回所有数据,然后在内存中执行FirstOrDefault
。我更喜欢这种情况发生在SQL中,但无论我尝试过什么,我都无法使其工作。
对于如何将FirstOrDefault函数转换为正确的SQL,您有任何建议吗?这样我就不会从数据库中检索太多东西了吗?
此外,我试过First
,Any
& Count
,所有这些都从数据库中获取所有行。
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;
}
}
}
我不得不来测试你的建议,但您的两个建议,使总的感觉!感觉有点密集,因为我没有发现它!我认为这是EF而不是我的失败! :) 谢谢! – Faraday
@Vijay还有一个想法 - 如果你所有的实体都有ID属性,那么考虑创建基本实体类'public abstract class Entity {public int ID {get;组; }}'为他们,并用'where T:Entity'参数化你的方法,因此你可以避免动态类型。当然,这只有在所有实体都具有相同类型的ID的情况下才有意义。 –
好的想法。我原本打算这样做,但有很多不同的类型。我想我可以不那么懒惰,为每个人编写解决方案......当我有时间看看它是否值得时,我会做一些基准测试。我知道动态不是太好,我倾向于在可能的情况下避免它们......再次感谢您的建议,非常感谢! – Faraday