利用 Linq to SQL 的数据访问层开发方式讨论
2008-05-15 12:16
197 查看
[align=left]为了较好的开发体验,在开发阶段,我喜欢用 Model -> DB 的次序来进行。
也就是说,先在程序中创建一个 Linq to SQL Data Classes 类,在设计视图上设计好类图。然后,程序中执行一下如下的代码来生成数据库:
if (db.DatabaseExists())
db.DeleteDatabase();
db.CreateDatabase();[/align]
这样做的好处是让我们可以以面向对象的方式去设计程序,而不必过早的纠缠于数据库的细节中去。
如果反过来,DB -> Model:
先在 SQL Server 2005 中设计好表,手工设置外键等细节,然后将这些表拖放到设计界面上去生成类。
这样的步骤,外键设置很容易出错,而且不容易设计继承关系。
像单表继承这样的工作,最终还是要在 dbml 的设计视图中去设置的。
还有一个坏处,就是生成的 Association,默认是双向关联的。但很多有时候我们需要的只是单向的关联,这也要到设计界面中去自己删除。
比如一个人可以有几个通讯地址:
生成 staff.Addresses 是有意义的,
而反过来 address.Staffs 就意义不大。
这样做有一个不好,就是每次调整设计(dbml)后,要重新生成数据库就会冲掉之前的测试数据。
为了这个目的,我们可以学习 Rails 中的思路,创建一个测试固件(Test Fixtures)项目.可以做成 Console Application, 加到解决方案中。
每次调整设计后,执行一遍即可。
在看了 Kigg Starter Kit 代码之后,我发现可以参考它的思路。我们可以定义一个 IDataService 接口,其中定义各种数据操作。
然后,再创建一个 DataContext 的 partial class. 让它继承这个接口,在其中包装一些相应的 linq to sql 操作,这样,UI 层的代码就可以做到很简单。
为了做到不和 Linq to SQL 的具体实现解耦,以便在将来也许需要替换掉 Linq to SQL 的实现。我们在接口层始终使用 IDataService 来操作数据,其具体的 Linq to SQL 实现可以用依赖注入框架来配置,如 Unity Application Block 等。
但这里我仍有疑问:实体如何传递呢?
一种办法是自己再定义一个独立的 Model 层,然后我们把 IDataService 的操作中返回的每一个结果都以 Model 层里定义的实体来表示。虽然利用 .NET 3.5 里的语法写起来不算太麻烦,但因为 Linq to SQL 已经有了实体定义了,自己再创建一层势必造成非常多的重复。扩展性是好了,但维护起来不容易。
另外,这样做也带来很多麻烦。比如在 Linq to SQL 里我们很多关联的实体集合可以设置为惰性加载。而返回自定义的实体集合后,就丧失了这个优势。否则,原来在 aspx 的界面里可以方便地: Eval("OrderDetails[0].UnitPrice") 获取关联信息,现在难道都要一次性加载出来吗?
从这个角度来看,使用 Linq to SQL 后,开发方便了,但是要做到清晰的分层,不太容易。
也许有人会说 ADO.NET Entity Framework 能做到这一点,但因为该框架还未正式发布,我也没有研究,这里不讨论。
所以,目前我的 Linq to SQL 开发方式是,创建 Data Context 的 partial class 来封装操作,以简化 UI 层的操作代码为指导原则。而需要传递实体集的地方,就仍然使用 Linq to SQL 产生的映射类。
如果 UI 层需要用到一个自定义的视图,则定义一个表示该视图的数据类用来返回。
大家有什么好的建议,欢迎讨论。
也就是说,先在程序中创建一个 Linq to SQL Data Classes 类,在设计视图上设计好类图。然后,程序中执行一下如下的代码来生成数据库:
if (db.DatabaseExists())
db.DeleteDatabase();
db.CreateDatabase();[/align]
这样做的好处是让我们可以以面向对象的方式去设计程序,而不必过早的纠缠于数据库的细节中去。
如果反过来,DB -> Model:
先在 SQL Server 2005 中设计好表,手工设置外键等细节,然后将这些表拖放到设计界面上去生成类。
这样的步骤,外键设置很容易出错,而且不容易设计继承关系。
像单表继承这样的工作,最终还是要在 dbml 的设计视图中去设置的。
还有一个坏处,就是生成的 Association,默认是双向关联的。但很多有时候我们需要的只是单向的关联,这也要到设计界面中去自己删除。
比如一个人可以有几个通讯地址:
生成 staff.Addresses 是有意义的,
而反过来 address.Staffs 就意义不大。
这样做有一个不好,就是每次调整设计(dbml)后,要重新生成数据库就会冲掉之前的测试数据。
为了这个目的,我们可以学习 Rails 中的思路,创建一个测试固件(Test Fixtures)项目.可以做成 Console Application, 加到解决方案中。
每次调整设计后,执行一遍即可。
在看了 Kigg Starter Kit 代码之后,我发现可以参考它的思路。我们可以定义一个 IDataService 接口,其中定义各种数据操作。
然后,再创建一个 DataContext 的 partial class. 让它继承这个接口,在其中包装一些相应的 linq to sql 操作,这样,UI 层的代码就可以做到很简单。
为了做到不和 Linq to SQL 的具体实现解耦,以便在将来也许需要替换掉 Linq to SQL 的实现。我们在接口层始终使用 IDataService 来操作数据,其具体的 Linq to SQL 实现可以用依赖注入框架来配置,如 Unity Application Block 等。
但这里我仍有疑问:实体如何传递呢?
一种办法是自己再定义一个独立的 Model 层,然后我们把 IDataService 的操作中返回的每一个结果都以 Model 层里定义的实体来表示。虽然利用 .NET 3.5 里的语法写起来不算太麻烦,但因为 Linq to SQL 已经有了实体定义了,自己再创建一层势必造成非常多的重复。扩展性是好了,但维护起来不容易。
另外,这样做也带来很多麻烦。比如在 Linq to SQL 里我们很多关联的实体集合可以设置为惰性加载。而返回自定义的实体集合后,就丧失了这个优势。否则,原来在 aspx 的界面里可以方便地: Eval("OrderDetails[0].UnitPrice") 获取关联信息,现在难道都要一次性加载出来吗?
从这个角度来看,使用 Linq to SQL 后,开发方便了,但是要做到清晰的分层,不太容易。
也许有人会说 ADO.NET Entity Framework 能做到这一点,但因为该框架还未正式发布,我也没有研究,这里不讨论。
所以,目前我的 Linq to SQL 开发方式是,创建 Data Context 的 partial class 来封装操作,以简化 UI 层的操作代码为指导原则。而需要传递实体集的地方,就仍然使用 Linq to SQL 产生的映射类。
如果 UI 层需要用到一个自定义的视图,则定义一个表示该视图的数据类用来返回。
大家有什么好的建议,欢迎讨论。
相关文章推荐
- 利用 Linq to SQL 的数据访问层开发方式讨论
- LINQ to Entities 实现sql 关键字"In"方式总结
- Asp.net网站开发(一)LINQ TO SQL 之动态数据支持
- Linq to Sql:三种事务处理方式
- Visual C# 2008+SQL Server 2005 数据库与网络开发--11.3.3 LINQ to SQL的数据库查询
- Microsoft ASP.NET MVC Preview 5 及LINQ TO SQL最新版开发示例演示(提供源码下载)
- LINQ to SQL:处理char(1)字段的方式会引起全表扫描问题
- LINQ to SQL:处理char(1)字段的方式会引起全表扫描问题
- Asp.net网站开发 Linq to SQL(增,删,改,查)
- asp.net Linq和泛型,IEnumerable和IQueryable之间的区别,Lambda表达式,Linq to Sql停止开发转为 Entity Framework
- Linq to Sql : 三种事务处理方式
- LINQ to Entities 实现sql 关键字"In"方式总结
- LINQ to Entities 实现sql 关键字"In"方式总结
- LINQ to Entities 实现sql 关键字"In"方式总结
- LINQ to Entities 实现sql 关键字"In"方式总结
- LINQ-to-SQL那点事~利用反射在LINQ-to-SQL环境中实现Ado.net的CURD操作
- 之前在开发中存在的一个关于Linq To SQL的错误认识。
- Linq to Sql : 三种事务处理方式
- VS2008开发-Linq to sql
- LINQ TO SQL中还是用传统的连接串方式建立DbContext更好些