我正处于建立新开发项目的早期阶段,我不确定如何设置我的数据库访问策略。我将使用Visual Studio 2012,并将以.NET 4.5和SQL Server 2008或2012为目标。实体框架,Dapper和SSDT的组合?
我不确定是否使用实体框架,如果是,使用实体框架。由于从数据库中读取数据然后处理它将成为此应用程序的主要工作,查询性能将变得非常重要。我知道EF5在这方面比EF4.x好很多,但这并不是我最担心的固有的EF开销(尽管Dapper至少有两倍的速度),但更多的是它为你提供的懒惰作为开发人员,因为通过LINQ查询太多太容易了。所以我希望纯SQL查询成为获取数据的主要方式。
不过,我会最怀念EF是:
- 编译时查询检查。
- 更改跟踪。
- 第一次开发代码。
- 工作模式的单位。
我可以在没有变更追踪的情况下生活,通常不难确定新增或更新的内容。
我所希望的是,这个项目的开发人员不必乱用表格设计师,但他们可以简单地编写POCO。所以为此,我非常欣赏EF的代码优先方法。有了这个,开发人员可以克隆源代码,请致电update-database
并拥有一个可工作的本地数据库。这在过去对我来说非常合适。
另一件对我来说非常重要的事情是一个工作模式单元,或插入和更新的原子性。我想排队所有更改,并有一个点,我拨打SaveChanges
。使用像DapperExtensions
这样的库,您会得到一个Insert
方法,但它会立即执行数据库调用。你可以通过在它周围包装一个事务来使它成为原子,但这与排队它不一样。所以我必须为此自行推出某种排队机制。
对于编译时查询检查,我考虑使用SQL Server数据工具(SSDT)。查询将是存储过程(以避免C#代码中的大型查询字符串blob)以及使用SSDT,这些可以在构建时检查。 SSDT的另一个优点是可以将存储过程从Visual Studio部署到目标数据库。最重要的是,这些SQL脚本将存在于源代码管理中。
因此,既然,我的解决方案将基本上由三个数据访问技术:
实体框架
- 将负责创建从POCO datamodels数据库。
- 将用于通过其工作模式插入/更新数据。需要注意的是,您首先必须将通过SQL获取的实体
Attach
添加到上下文中。
SSDT
- 将用于在编译时间来验证SQL脚本。
- 允许脚本存在于Git中。
- 将部署EF无法部署到您的数据库的东西。
小巧玲珑/其他微型ORM
- 将用于获取数据
我不禁觉得这是一个有点怪人解决方案,我用各种的一切的零碎。我还不确定SSDT和EF会以一种很好的方式一起工作。这个快速的例子似乎工作正常,但:
// Combo of Dapper, EF and a stored proc that was published through SSDT
static void Main(string[] args)
{
var connectionString = ConfigurationManager
.ConnectionStrings["DbDataContext"].ConnectionString;
using (var conn = new SqlConnection(connectionString))
using (var ctx = new DbDataContext())
{
conn.Open();
var product = conn.Query<Product>("GetProduct",
commandType: CommandType.StoredProcedure).First();
ctx.Products.Attach(product);
var order = new Order
{
Product = product
};
ctx.Orders.Add(order);
ctx.SaveChanges();
}
}
这种方法似乎可以工作,但它也很混乱。但是如果我放弃SSDT,我会错过SQL的编译时检查,如果我放弃实体框架,我会错过代码优先和更容易的插入,如果我放弃直接SQL,我会错过大量的表现。
是否有替代品可以忽略?如果不是,这里最好的办法是什么?
“作为开发者提供的懒惰” - 这是你的工作,不要懒惰; EF提供完美的性能工程。 – millimoose
是的,但不使用LINQ。你必须下到原始的SQL,然后它仍然只有普通ADO.NET/Dapper(http://goo.gl/ctD9f)的一半。不妨跟Dapper一起去查询。然而,我想避免在C#代码中查询大字符串的匿名blob,这就是为什么我查看SSDT将其移出代码的原因。 – JulianR
好的,但这是开发人员控制之外的框架开销问题。我的观点仅仅是“提供懒惰”不是选择或不选择技术的好理由。如果您愿意为ORM“深度”交换开销,您仍然可以选择避免由N + 1选择问题导致的性能问题。 (这个问题对性能的影响也很大,在原始SQL中也很容易遇到,而且解决起来更具挑战性,因为在SQL中编写大量的uberqueries比LINQ更困难。) – millimoose