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

jer*_*mny 10 .net c# linq entity

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

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

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

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

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

Ham*_*ein 11

在您需要更复杂的查询之前,Linq的强大功能并没有真正显现出来.

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

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

IQueryable<Table> results = from query in context.Table
                            where query.ForeignKeyId = fldToSearchFor
                            select query;
Run Code Online (Sandbox Code Playgroud)

你可以把它拿走并制作它;

results.Where( r => r.Value > 5);
Run Code Online (Sandbox Code Playgroud)

结果sql看起来像;

SELECT * FROM Table WHERE ForeignKeyId = fldToSearchFor AND Value > 5
Run Code Online (Sandbox Code Playgroud)

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


ken*_*n2k 10

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

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

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

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


Gro*_*roo 5

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

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

此外,您可以传递部分构造的查询,只有在需要时才会对它们进行延迟计算.

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


Pau*_*ner 5

LINQ是否将您的所有查询硬编码到您的应用程序中?是的,一点没错.

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

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

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

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

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

在这种非常具体的情况下,您要么不对查询进行外部更改,要么应用程序忽略更改,您将获得部署仅SQL更改的能力,而无需触摸应用程序或将其降低到任何数量时间(或者如果您进入桌面,部署新版本).


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

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