MVC多表联合查询数据显示
随然做过几年.net开发,但一直没有做过MVC框架下的网站,这段时间无事,学习一下。下面的方法是我摸索过程中的一点总结,如果有更好的方法,欢迎告诉我,谢谢。
这段时间我只看了MVC和LinQ两本书,关于EF我是没看的,所以我的这个网站的数据层打算直接使用LinQ完成。今天准备开发了,才发现读数据是个问题,汗呀~~~
现在总结两种方法:
1.手写实体对象。
思路:写一个包含所有字段属性的实体类对象,使用LinQ将数据查询出后,经过一个转换器将数据转换为IList<T>类型,返回给视图显示。
1.实体类对象。
public class IndexAtriclList { /// <summary> /// 主键ID /// </summary> public int ID { get; set; } /// <summary> /// 标题 /// </summary> public string Title { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreateTime { get; set; } /// <summary> /// 创建人 /// </summary> public string UserName { get; set; } }
2.读取数据。
DataClasses1DataContext context=new DataClasses1DataContext(); //方法1 var query = from a in context.GetTable<Articles>() join m in context.GetTable<Members>() on a.AutherID equals m.ID orderby a.CreateTime select new IndexAtriclList { ID = a.ID, Title = a.Title, CreateTime = a.CreateTime, UserName = m.UserName }; var list = Common.ToList<IndexAtriclList>(query);
return View(list);
上面这段代码中DataClasses1DataContext是LinQ To SQL设计器自动生成的代码,包括了DataContext对象及所有数据表映射。
Common.ToList是我写的一个转换器,下面会说到。
Articles,Members是LinQ的数据表映射,IndexAtriclList是第1步生成的实体对象。
3.转换数据
public class Common { public static List<T> ToList<T>(IEnumerable<T> data) { List<T> list=new List<T>(); var propertys = System.ComponentModel.TypeDescriptor.GetProperties(typeof(T)); foreach (var item in data) { T t = Activator.CreateInstance<T>(); Type type = t.GetType(); foreach (System.ComponentModel.PropertyDescriptor p in propertys) { object o=p.GetValue(item); t.GetType().GetProperty(p.Name).SetValue(t, o, null); } list.Add(t); } return list; } }
这里我用到了泛型,想的是方法的复用,主要是想省事。
4.视图显示
@model IList<IndexAtriclList> <h2>Index</h2> <table border="1"> <thead> <tr> <td>标题</td> <td>发布日期</td> </tr> </thead> @{ foreach (var item in Model) { <tr> <td>@item.Title</td> <td>@item.CreateTime</td> </tr> } } </table>
ok,到这里第一种方法完成。但是我还没想明白,如果这么做的话,手写及维护实例类就是一项艰巨的工作,不知是我的思路不对,还是有更好的方法,希望大家指正。
2.存储过程
思路:在sql server中写一个返回结果集的存储过程,LinQ直接调用即可。(这个方法真是太方便了,两分钟搞写)
1.在Sql Server中写存储过程
Create proc IndexArticleList as select a.ID,Title,a.CreateTime,m.UserName from Articles a inner join Members m on a.AutherID=m.ID go
2.调用存储过程
DataClasses1DataContext context = new DataClasses1DataContext(); //方法2 var list = context.IndexArticleList().ToList();
return View(list);
3.视图显示,方法同第1种方法。
这个方法不用我们维护实体类,LinQ会根据存储过程自动生成对应的类。我们可以在LinQ的designer.cs上看到生成的对象。
public partial class IndexArticleListResult { private int _ID; private string _Title; private System.DateTime _CreateTime; private string _UserName; public IndexArticleListResult() { } [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ID", DbType="Int NOT NULL")] public int ID { get { return this._ID; } set { if ((this._ID != value)) { this._ID = value; } } } ......................
如果有一个复杂的查询逻辑,我们可以写在存储过程中,提升性能。
我在测试当中,发现LinQ对返回多结果集的存储过程支持并不好,每次辛辛苦苦改了LinQ的映射文件,一刷新又变回去了。不知道该说什么了。关于返回多结果集的方法,我会在下一篇中总结。