如何使用Entity + LINQ而不仅仅是对我的查询进行硬编码?

时间:2012-01-16 12:08:16

标签: c# .net linq entity

所以我现在已经开始使用Entity + LINQ了,我真的开始怀疑最佳实践。我习惯了“如果我需要获取数据,引用存储过程”的模型。如果需要,可以动态更改存储过程,不需要重新编译代码。我发现我的代码中的查询看起来像这样:

List<int> intList = (from query in context.DBTable
                     where query.ForeignKeyId == fkIdToSearchFor
                     select query.ID).ToList();

我开始想知道它与此之间的区别是什么:

List<int> intList = SomeMgrThatDoesSQLExecute.GetResults(
                                  string.Format("SELECT [ID]
                                                 FROM DBTable
                                                 WHERE ForeignKeyId = {0}",
                                  fkIdToSearchFor));

我担心的是,我基本上很难将查询编码到代码中。我错过了什么吗?这是实体的意义吗?如果我需要做任何真正的查询工作,我应该把它放在一个sproc中吗?

5 个答案:

答案 0 :(得分:11)

在您需要更复杂的查询之前,Linq的力量并没有真正显现出来。

在您的示例中,如果您想将某种形式的过滤器应用于查询,请考虑您需要执行的操作。使用字符串构建的SQL,您必须将值附加到字符串构建器中,以防止SQL注入(或者通过参数准备语句的额外工作)。

假设你想在你的linq查询中添加一个语句;

IQueryable<Table> results = from query in context.Table
                            where query.ForeignKeyId = fldToSearchFor
                            select query;

你可以接受并制作它;

results.Where( r => r.Value > 5);

生成的sql看起来像;

SELECT * FROM Table WHERE ForeignKeyId = fldToSearchFor AND Value > 5

在您枚举结果集之前,您想要装饰的任何额外条件都将为您添加,从而产生更灵活,更强大的动态查询方式。我使用这样的方法在列表上提供过滤器。

答案 1 :(得分:10)

我个人避免硬编码SQL请求(作为你的第二个例子)。编写LINQ而不是实际的SQL允许:

  • 易用性(智能感知,类型检查......)
  • LINQ语言的强大功能(当存在一些复杂性,多个连接等等时,大多数时候它比SQL更简单。)
  • anonymous types
  • 的力量
  • 现在在编译时看到错误,而不是在两个月后的运行时...
  • 如果你想重命名一个表/列/的话,可以更好地重构...(你不会忘记用LINQ重命名任何东西,因为编译时检查)
  • 您的请求和数据库之间的松散耦合(如果您从Oracle迁移到SQL Server会怎么样?使用LINQ您将不会更改您的代码,使用硬编码请求您将不得不审查所有请求)
  • LINQ vs存储过程:您将逻辑放在代码中,而不是放在数据库中。请参阅讨论here
  

如果我需要获取数据,请引用存储过程。存储过程   可以根据需要动态更改,不需要重新编译代码

- &GT;如果您需要更新模型,您可能还需要更新代码以考虑更新数据库。所以我认为它不会帮助你避免在大多数时候重新编译。

答案 2 :(得分:5)

是的,如果你擅长SQL,你可以通过存储过程得到所有这些,并从更好的性能和一些维护优势中受益。

另一方面,LINQ是类型安全的,稍微更容易使用(因为开发人员习惯于非db场景),并且可以与不同的提供者一起使用(它可以转换为特定于提供者的代码)。任何实现IQueriable的东西都可以和LINQ一样使用。

此外,您可以传递部分构造的查询,只有在需要时它们才会被延迟评估。

所以,是的,你 对它们进行硬编码,但实质上,它是你的程序的逻辑,并且它的硬编码就像其他任何部分一样你的源代码。

答案 3 :(得分:5)

LINQ是否将您的所有查询硬编码到您的应用程序中?是的,绝对。

让我们考虑一下这对您的应用程序意味着什么。

如果要更改获取某些数据的方式,则必须对已编译的代码进行更改;你不能对你的数据库做一个“修补程序”。

但是,如果由于数据模型的更改而更改了查询,则可能需要更改域模型以适应更改。

假设您的模型未更改且查询正在更改,因为您需要向查询提供更多信息以获得正确的结果。这种更改当然要求您更改应用程序以允许使用新参数为查询添加其他过滤。

再次,假设您很乐意为新参数使用默认值,应用程序不需要指定它。查询可能包含一个字段作为结果的一部分。您不必使用此附加字段,并且可以忽略通过网络发送的其他信息。它在这里引入了一些维护问题,因为你的SQL与你的应用程序对它的解释是不一致的。

在此非常特定情况下,您要么不对查询进行外部更改,要么应用程序忽略更改,您将获得部署仅SQL更改的能力,而无需触摸应用程序或将其关闭任何时间(或者如果您进入桌面,部署新版本)。


实际上,当谈到对系统进行更改时,大部分时间都花在设计和测试查询上,而不是部署它们(如果不是,那么你在一个可怕的地方)。在LINQ中查询的好处是,它可以更容易地编写和测试它们,而不受其他因素的影响,如单元测试或部分其他过程。

在LINQ上使用存储过程的唯一真正原因是,如果要在SQL层使用一致的API在多个系统之间共享数据库。这是一个非常可怕的情况,我宁愿在SQL数据库的顶部开发一个服务层来摆脱这种设计。

答案 4 :(得分:3)

我也想知道这一点,但数据库交互仅在数据库 中的心态是一种过时的概念。拥有专门的dba流失存储过程,而多个前端开发人员等待,确实是开发资金的低效使用。

Java商店坚持这种范式,因为他们没有像linq这样的工具,并且由于必要性而坚持这种范式。使用.Net的数据库发现,如果没有完全删除数据库人员的需求会被减少,因为一旦结构到位,数据可以更有效地 操纵 (如图所示)这个帖子的所有其他响应者)在数据层中使用linq而不是原始SQL。

如果有人有机会使用code first并从头开始创建数据库模型,首先在代码中生成实体类,然后运行EF以实现真正的魔力创建数据库...人们理解数据库是如何真正成为存储数据的工具以及存储过程的需要,并且不需要专用的dba。