日期:2014-05-20  浏览次数:20718 次

没有问题,散分:介绍我们是如何为程序插上Linq的翅膀的?!
这里是我对面向对象数据库的接口定义:

public interface IDomain : IDisposable
{
  void Save(object obj); //更新和新增是同一个方法。
  void Delete(object obj);
  void Commit();
  void Rollback();
  IEnumerable<T> Cast<T>();
}

当然其实现方法应该尽量满足我在另一个帖子中的描述。

例如我们要创建一个系统用户,同时把它注册到“出差不报销”和“干活不拿钱”两个用户组里边,我们可以写:

using(var x=new Domain(服务器的Endpoint))
{
  var newUser=new User{Name="张三", Password="adfadf", Email="zhang@hotmail.worldcomputer};
  var userGroups=from Group g in x where g.Name=="出差不报销" || g.Name=="干活不拿钱" select g;
  userGroup.Foreach(g=> 
  {
  g.AddUser(newUser);
  x.Save(g);
  });
  x.Commit();
}

由于面向对象的ORM应该自动保存缓冲区中的所有“脏”对象,因此我们并不需要保存那个newUser,保存(更新)Group就自动保存了newUser。

在IDomain这里,实际上只有Cast是新的(相对于数据库历史而言),是Linq给我们带来的优雅的查询方案。如果我的数据库存储是DataTable,那么我只要在一个static class中这样写一个扩展方法:

static public IEnumable<T> Cast<T>(this DataTable tbl) where T:User
{
  var ret=new List<User>();
  foreach(DataRow r in tbl.rows)
  ret.Add(new User{Name=r["name"],Email=r["email"],Password=r["password"]});
  return ret;
}

这样就可以在任何地方写查询:

DataTable tbl= myDataSets.Table["users"];
var query=from User u in tbl where u.Name=="张三" select u;

我在IDomain接口中的仅仅Cast这一个定义,类似于上面我们对保存有User类对象的DataTable追加一个Cast方法的做法,对于你的任何原先的数据库设计只要增加这一个方法,就跟Linq“挂上了钩”,可以享受到Linq的功能了。当然,如果你觉得我写的DataTable的Cast方法效率不高,可以再使用QueryProvider的概念去重新设计Cast(例如返回一个IQueryable<T>类型的结果),使得query自己在运行时编译自己的查询规划步骤。但是无论如何,Linq是非常容易使人对任何“旧的”数据管理程序中的查询进行翻新的。不是只有linq to sql之类现成的那几个类库才用到了Linq,我们从自己的“旧的”数据管理程序出发去扩展出Cast,就能用Linq处理旧的程序对象了。将旧的对象类型,看起来完全不可能为了查询语法改变而重写一边的业务类型,很轻便地利用Linq处理,这才是Linq的最激动人心的地方!

------解决方案--------------------
传说中使用泛型都是超级NB的家伙
什么时候我才能象楼主一样写出让菜鸟们看不懂的东西啊
------解决方案--------------------
楼主不是一般的高人,做个记号。

另外,楼主能不能看下这个帖子,http://topic.csdn.net/u/20080517/12/91f60f4c-1fbe-4299-8677-37f08d8034ac.html,蒋老大只给一个思路,我实现不了。