我使用的是ASP.NET Core 1.0,网站很大(每小时约有5,000名访问者)。我已多次阅读过存储过程非常快速和安全(就SQL注入而言)。但代码首先EF如果这么容易,我想使用它,但CRUD方法是隐藏的。
在性能和安全性方面,使用EF over SP的Scaffolding会有什么缺点(如果有的话)?
答案 0 :(得分:3)
只要您使用参数化SQL,就SQL注入而言应该没问题。切勿直接使用用户输入" build"通过字符串连接进行SQL查询。因此,只要您正确使用实体框架,存储过程或其他工具,就不必担心SQL注入。
在性能方面,实体框架和其他类似工具的整体表现更差。我不确定单独是否足以阻止您使用它,除非您的程序预计使用量非常大。
Stack Exchange有一个很好的开源工具Dapper比实体更轻量级但仍然有一些不错的功能。它允许您编写原始SQL。请参阅Dapper readme中有关效果的部分。它表现得非常好,比其他框架好得多。
远离存储过程有助于改善您的体系结构。存储过程可能会鼓励您在数据库中编码大量业务逻辑,而单元和集成测试更难以完成。此外,由于必须保持应用程序,存储过程和架构同步,部署新应用程序变得更加困难。
因此,简而言之,实体框架是一个很好的工具,但可以降低性能。存储过程的替代方案仍然具有高性能。对于您使用的任何成熟工具(正确),安全性不应成为问题。
编辑以回答其他问题
不熟悉SQL注入吗?
当然,但如果使用不当,几乎任何工具。以下是从文档中使用Dapper示例的正确方法。此查询已参数化。
connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
)
现在,这是一个容易受到SQL注入的错误示例:
connection.Execute(@"insert MyTable(colA, colB) values ('" + a + "', '" + b + "')")
实体框架是否始终安全?
不,如果您连接上一节中的变量并使用ExecuteQuery,那么您也会遇到问题。
存储过程是否始终安全?
不,如果在没有参数化的情况下使用动态SQL,仍会遇到SQL注入问题。
这是一个讨论ORM和存储过程如何易受SQL注入影响的链接:http://www.troyhunt.com/2012/12/stored-procedures-and-orms-wont-save.html
在性能和安全性方面使用Scuffolding与EF over SP相比会有什么缺点(如果有的话)?
如上所述,如果使用得当,则无安全问题。如果你正在做CRUD页面,脚手架很棒。
如果您需要进行高级报告,则可能需要使用自定义SQL,这仍然可以使用Entity Framework完成。使用脚手架对你的应用程序来说没有任何问题,因为使用它是有意义的,然后通过实体使用参数化的SQL来实现其他一切。您甚至可以使用脚手架,然后修改生成的类来执行您想要的操作。对于CRUD页面,使用脚手架和高级查询编写自己的。
使用实体框架进行简单查询所带来的性能可能不会让您受到基本查询的伤害 - 它应该是最小的。您最需要担心的是正确的索引和数据库模式。错误的架构或不正确的索引会导致性能问题匆忙。
答案 1 :(得分:0)
我喜欢在编写存储过程和在EF中编写查询之间做出选择,类似于(在某种程度上)汇编程序编程与编写在托管环境(如.NET和Java)中运行的程序之间的差异。为托管环境编写的应用程序总是比使用汇编语言编写的应用程序慢,但另一方面,使用托管语言编写复杂的应用程序通常要容易得多(因此也更便宜)。使用EF linq,您可以更快地编写查询,它们通常比它们的sql更简单,因此更容易维护。其他重要因素是应用程序快速变化,新功能正在被添加,旧功能正在被重写,以及此流程表和其他数据库结构的变化。发生这种情况时,您的SP无法再正常工作。你什么时候知道应该修复它们?只有当你运行它们时。您何时知道需要修复EF查询,因为表更改?在编译期间。而且性能下降了?一般来说,现在我们拥有快速且相当便宜的机器,所以我们并不在乎这么多。我检查了一次EF查询的执行时间及其sql等价物 - 普通sql使我的执行时间减少了5% - 这对我来说没什么。而且由于sql查询要复杂得多,因此很有可能以错误的方式编写查询,这样就不必再慢了。最后,如果您需要在应用程序中为某些复杂查询提供非常出色的性能 - 将其写为SP并使用EF轻松执行。
说到安全性,EF查询生成器总是使用sql参数,因此它们与SP一样安全地进行sql注入。
答案 2 :(得分:0)
您可以使用scaffolding创建数据库和视图,并使用您自己的方法替换对内置方法的调用。