实体框架 - 在使用它们之前检查单个记录的正确方法
Posted
技术标签:
【中文标题】实体框架 - 在使用它们之前检查单个记录的正确方法【英文标题】:Entity Framework - Correct way to check for single records before using them 【发布时间】:2010-01-26 20:59:50 【问题描述】:为了获得记录列表,我通常会按照以下方式进行操作:
var efCompany = from a in _dbRiv.Company where a.CompanyId == companyFeedInfo.CompanyId select a;
要获取单个记录,当我知道我正在使用 PK 来检索它时,我会使用以下内容:
var efCompany = (from a in _dbRiv.Company where a.CompanyId == companyFeedInfo.CompanyId select a).First();
现在,使用单记录方法,如果 PK 是错误值(就像它故意在测试中一样),第二行会引发错误。
获取单个记录并处理它的最佳实践方法是什么?
【问题讨论】:
【参考方案1】:如果您期望 0 或 1,请使用 SingleOrDefault
,或者如果您只需要可能的许多记录中的第一条记录,但可以处理 0,请使用 FirstOrDefault
。如果满足以下条件,两者都将返回该类型的默认值(通常为 null)没有结果。
顺便说一句,像这样的查询通常更易读(IMO)没有使用查询表达式,所以你可能有类似的东西:
var efCompany = _dbRiv.Company
.Where(a => a.CompanyId == companyFeedInfo.CompanyId)
.SingleOrDefault();
if (efCompany != null)
// Use it
else
// Report to user, or whatever
当您使用多个运算符或执行相对复杂的操作(如连接)时,查询表达式非常有用 - 但如果您只是有一个where
子句或只是 有一个投影,这个“点符号”更简单 IMO。当您需要在最后调用FirstOrDefault
之类的方法时,它也可以更好地工作。
【讨论】:
感谢您对查询表达式的补充评论。仍然在 EF 上学到了很多东西,我的想法并没有完全围绕 lambda 语法。让我想起了很多旧的 C 内存指针。 ;)SingleOrDefault
在 EF 4 中受支持,但在 EF 1 中不支持。FirstOrDefault
在两者中均受支持。
@Jon Skeet - 将订单后备词放在 LINQ 链上有什么区别......例如。 _db.MyModels.Where(a => a.Prop == "value").SingleOrDefault();
与 _db.MyModels.SingleOrDefault().Where(a => a.Prop == "value");
- 性能?执行令?等等……
@one.beat.consumer:第二个甚至不会编译(通常),因为 SingleOrDefault 返回单个值,而不是序列。但如果它确实 编译,它就不会做你想做的事。它会检查整个 MyModels 表中是否只有一个值,然后对其应用过滤器。
@JonSkeet 我在输入之后就意识到了这一点。这个怎么样:_db.Models.Select(model => new ViewModel Prop = model.Prop ).ToList().Where(viewModel => viewModel.Prop = "value");
与 _db.Models.Select(model => new ViewModel Prop = model.Prop ).Where(viewModel => viewModel.Prop = "value").ToList();
- 这些不同的含义是什么?任何性能差异?数据库活动?选角问题?只是好奇【参考方案2】:
请注意,SingleOrDefault()
和 FirstOrDefault()
都不允许您指定默认值。
有DefaultIfEmpty()
,它允许您指定如果枚举中没有项目时要返回的默认值。您可以将它与First()
(如DefaultIfEmpty().First()
)结合使用,以实现FirstOrDefault()
类似的行为,并使用lambda 来包装创建一个新实例并将其添加到集合中。
如果只需要检查记录是否存在,也可以使用Any()
。但是,如果您需要处理记录(如果存在),这将导致两次查询。
【讨论】:
如果您只需要检查是否存在,Any() 是最好的方法。DefaultIfEmpty
与 SingleOrDefault
一样,在 EF 4 中受支持,但在 EF 1 中不受支持。
我知道这已经 8 岁了,但有没有机会举个例子?
@Cloud 抱歉,我在过去七年左右没有接触过任何微软技术,所以... :-/
if (yourDataTable.Any()) if (yourDataTable.Any(x => x.Field == True || x.OtherField == "Test") @Cloud 是这个你想要的例子?【参考方案3】:
var efCompany = _dbRiv.Company
.SingleOrDefault(a => a.CompanyId == companyFeedInfo.CompanyId);
if (efCompany != null)
// Use it
else
// Report to user, or whatever
【讨论】:
【参考方案4】:你也可以使用
_dbRiv.Company.find(#id)
如果您正在寻找没有包含模型的记录。
或者
_dbRiv.Company.FirstOrDefault(x => x.Id == #id);
考虑到性能,我推荐 FirstOrDefault 而不是 SingleOrDefault。使用 SingleOrDefault 它需要扫描整个表并确保只有一条带有 Id 的记录。使用 FirstOrDefault 它可以简单地运行,直到找到该 id 然后停止。在大表上,每次查询都会为您节省少量时间。
如果您不需要跟踪对模型所做的任何更改,您还可以使用 AsNoTracking 来改善内存消耗。例如,如果您通过休息请求返回它而不调用保存。
【讨论】:
我猜如果有索引就不需要扫描整个表了。以上是关于实体框架 - 在使用它们之前检查单个记录的正确方法的主要内容,如果未能解决你的问题,请参考以下文章