您的位置:首页 > 运维架构 > 网站架构

一个基于EntityFramework的DAO (反射出架构信息并应用在CRUD中)

2010-07-08 23:03 621 查看
满是坎坷的完成了这个DAO,间或断了几次,对MSDN欲求不满,还好Google在.

在VS中生成了映射文件,以及实体类后,简单配置一下就可以使用了,请各位指点迷津,这样写法是否妥当,千万别把这个类拿去搞生产,否则后果自负,作者不承担任何后果.

我们知道,一般的项目都是分了几层,而其中少不了对于数据持久化的管理,也就是数据访问层,在被Hibernate的配置淹没后,被DbEntry.net(国产推荐!)的总总不适后又投向了M$自己的EntityFramework,但是也不能直接拿来用,万一以后又要转向其他数据源,那改动就真的是欲哭无泪了.所以免不了对其封装一番.好在C#是一门相当灵活的语言,通过反射,我们可以进行对程序自己的解析.下面我就将我对EF简单封装后的一个DAO以及一些体会和大家分享,经验不足难免有误人子弟的嫌疑,欢迎各位指正.

如何获得实体类的映射信息
在EF映射信息生成后编译,然后在使用项目中引用,反射得到映射资源,一般是个目录下,怎样得知映射文件名?在EF连接字符串中可以获得.在metadata节点可获得.
metadata=res://*/School.csdl|res://*/School.ssdl|res://*/School.msl;
如何读取映射信息
通过XML操作可以获得,不过在这里我碰到了个问题,就是有名称空间的节点以及属性该如何访问,试了几次,以为Xpath没写对,结果参照XPathVisualizer(一个开源项目,用于验证Xpath)显示结果是正确的,后来在其源码中找到了读取有名称空间的节点以及属性的方法,大致思路就是获得所有名称空间并在检索xpath时提供这些名称空间.

1 private XmlNamespaceManager getAllNamespace(XmlDocument doc)
2 {
3 XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
4 XPathNavigator nav = doc.CreateNavigator();
5 XPathNodeIterator list = nav.Select("//namespace::*[name() != 'xml'][not(http://www.cnblogs.com/namespace::*=.)]");
6 Dictionary<string, string> xmlNamespaces = new Dictionary<string, string>();
7 int c = 1;
8 while (list.MoveNext())
9 {
XPathNavigator nsNode = list.Current;
if (nsNode.NodeType == XPathNodeType.Namespace)
{
string ns = nsNode.Value;
if (!xmlNamespaces.Values.Contains(ns))
{
// get the prefix - it's either empty or not
string origPrefix = nsNode.LocalName;

// make sure the prefix is unique
int dupes = 0;
string actualPrefix = origPrefix;
while (actualPrefix == "" || xmlNamespaces.Keys.Contains(actualPrefix))
{
actualPrefix = (origPrefix == "")
? String.Format("ns{0}", c++)
: String.Format("{0}-{1}", origPrefix, dupes++);
}
xnm.AddNamespace(actualPrefix, ns);
xmlNamespaces.Add(actualPrefix, ns);
}

}
}
return xnm;
}
"it"别名
在EF构造SQL语句的时候,使用的是"it"作为默认别名,所以在进行SQL操作的时候记得要加上"it."作为前缀.

读取出数据后记得移除读取对象与ObjectContext的联系
仅仅只是toList返回对象后还要为每个对象Detach,解除绑定才能进行一些后续操作,否则无法再次访问数据库(当然,除非是在同一个ObjectContext下)

修改
修改的时候如果不是同一ObjectContext读取的,那么还需要使用该上下文来读取出对象,否者会报错.详细的讨论:http://social.msdn.microsoft.com/Forums/en-SG/adodotnetentityframework/thread/501d7b99-0cb9-44b6-b2cd-16275a151b31

全部代码 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using System.Configuration;
7 using System.Data.Objects;
8 using System.Data.EntityClient;
9 using System.Xml;
10 using System.Xml.XPath;
11 namespace ES.DAL
12 {
13 public class DataService<T>
14 where T : System.Data.Objects.DataClasses.EntityObject
15 {
16 private static Type contextType;
17 private static XmlDocument doc;
18 private static string entityContainer;
19
20 private string tableName;
21 private string keyName;
22 private Dictionary<string, Type> propertype;
23
24 static DataService()
25 {
26 contextType = Type.GetType(ConfigurationManager.ConnectionStrings[DataService.EFObjectContext].ConnectionString);
27
28 EntityConnectionStringBuilder scsb = new EntityConnectionStringBuilder(ConfigurationManager.ConnectionStrings[DataService.ConnectionString].ConnectionString);
29 string str = scsb.Metadata.Split('|').Single(x => x.EndsWith(".csdl"));
30 var ls = contextType.Assembly.GetManifestResourceStream(str.Substring(str.LastIndexOf('/') + 1));
31 using (System.IO.StreamReader reader = new System.IO.StreamReader(ls))
32 {
33 string csdlData = reader.ReadToEnd();
34 doc = new XmlDocument();
35 doc.LoadXml(csdlData);
36 }
37 }
38
39 private ObjectContext getInstence()
40 {
41 return (ObjectContext)Activator.CreateInstance(contextType);
42 }
43
44 private XmlNamespaceManager getAllNamespace(XmlDocument doc)
45 {
46 XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
47 XPathNavigator nav = doc.CreateNavigator();
48 XPathNodeIterator list = nav.Select("//namespace::*[name() != 'xml'][not(http://www.cnblogs.com/namespace::*=.)]");
49 Dictionary<string, string> xmlNamespaces = new Dictionary<string, string>();
50 int c = 1;
51 while (list.MoveNext())
52 {
53 XPathNavigator nsNode = list.Current;
54 if (nsNode.NodeType == XPathNodeType.Namespace)
55 {
56 string ns = nsNode.Value;
57 if (!xmlNamespaces.Values.Contains(ns))
58 {
59 // get the prefix - it's either empty or not
60 string origPrefix = nsNode.LocalName;
61
62 // make sure the prefix is unique
63 int dupes = 0;
64 string actualPrefix = origPrefix;
65 while (actualPrefix == "" || xmlNamespaces.Keys.Contains(actualPrefix))
66 {
67 actualPrefix = (origPrefix == "")
68 ? String.Format("ns{0}", c++)
69 : String.Format("{0}-{1}", origPrefix, dupes++);
70 }
71 xnm.AddNamespace(actualPrefix, ns);
72 xmlNamespaces.Add(actualPrefix, ns);
73 }
74
75 }
76 }
77 return xnm;
78 }
79 public DataService()
80 {
81 tableName = typeof(T).Name;
82 XmlNamespaceManager xnm = getAllNamespace(doc);
83 entityContainer = doc.SelectSingleNode(".//ns1:EntityContainer", xnm).Attributes["Name"].Value;
84 var cur = doc.SelectSingleNode("//ns1:EntityType[@Name=\"" + tableName + "\"]", xnm);
85 XmlNodeList pros = cur.SelectNodes(".//ns1:Property", xnm);
86 propertype = new Dictionary<string, Type>();
87 for (int i = 0; i < pros.Count; i++)
88 {
89 XmlNode node = pros[i];
90
91 //System.Collections.IEnumerator itor = node.Attributes.GetEnumerator();
92 //while (itor.MoveNext())
93 //{
94 // XmlAttribute a = (XmlAttribute)itor.Current;
95
96 //}
97
98 if (node.Attributes["StoreGeneratedPattern", xnm.LookupNamespace("annotation")] != null)
99 keyName = node.Attributes["Name"].Value;
propertype.Add(node.Attributes["Name"].Value, Type.GetType(node.Attributes["Type"].Value));
}
}
/// <summary>
/// 执行Linq表达式返回List
/// </summary>
/// <param name="linq">接受一个QbjectQuery,返回IEnumerable的表达式</param>
/// <returns>List</returns>
public List<T> Linq(Func<ObjectQuery<T>, IEnumerable<T>> linq)
{
using(var context = getInstence())
{
return linq(context.CreateQuery<T>("[" + tableName + "]")).ToList<T>();
}
}
public List<T1> Linq<T1>(Func<ObjectQuery<T>, IEnumerable<T1>> linq)
{
using (var context = getInstence())
{
return linq(context.CreateQuery<T>("[" + tableName + "]")).ToList<T1>();
}
}

public T FindById(object keyValue)
{
var key = new System.Data.EntityKey(entityContainer + "." + tableName, keyName, keyValue);
using (var context = getInstence())
{
T result = (T)context.GetObjectByKey(key);
context.Detach(result);
return result;
}
}

public List<T> Find()
{
return Find(0, -1, x => true, keyName, false);
}
public List<T> Find(Func<T, bool> wherecase)
{
return Find(0, -1, wherecase, keyName, false);
}
public List<T> Find(Func<T, bool> wherecase, bool isdescending)
{
return Find(0, -1, wherecase, keyName, isdescending);
}
public List<T> Find(int start, int len)
{
return Find(start, len, null, keyName, false);
}
public List<T> Find(int start, int len, Func<T, bool> wherecase)
{
return Find(start, len, wherecase, keyName, false);
}
public List<T> Find(int start, int len, Func<T, bool> wherecase, string orderKey)
{
return Find(start, len, wherecase, orderKey, false);
}
public List<T> Find(int start, int len, Func<T, bool> wherecase, string orderKey, bool isdescending)
{
using (var context = getInstence())
{
ObjectQuery<T> query = context.CreateQuery<T>("[" + tableName + "]").OrderBy(orderKey);
orderKey = orderKey.StartsWith("it.") ? orderKey : "it." + orderKey;
IEnumerable<T> result;
if (wherecase != null)
result = query.Where(wherecase);
else
result = query.AsEnumerable();
result = result.Skip(start);
result = len == -1 ?
isdescending ?
result.Reverse()
:
result
:
isdescending ?
result.Take(len).Reverse()
:
result.Take(len);
List<T> list = result.ToList();
list.ForEach(x => context.Detach(x));
return list;
}
}

public void Save(T o)
{
using (var context = getInstence())
{
context.AddObject(tableName, o);
context.SaveChanges();
}
}
public void Save(IEnumerable<T> listo)
{
using (var context = getInstence())
{
foreach (T i in listo)
{
context.AddObject(tableName, i);
}
context.SaveChanges();
}
}
public void Update(T o)
{
using (var context = getInstence())
{
//fix
//http://social.msdn.microsoft.com/Forums/en-SG/adodotnetentityframework/thread/501d7b99-0cb9-44b6-b2cd-16275a151b31
object original = context.GetObjectByKey(o.EntityKey);
context.ApplyPropertyChanges(tableName, o);
context.SaveChanges();
}
}
public void Update(IEnumerable<T> listo)
{
using (var context = getInstence())
{
foreach (T o in listo)
{
object original = context.GetObjectByKey(o.EntityKey);
context.ApplyPropertyChanges(tableName, o);
}
context.SaveChanges();
}
}
public void Delete(T o)
{
using (var context = getInstence())
{
object original = context.GetObjectByKey(o.EntityKey);
context.DeleteObject(o);
context.SaveChanges();
}
}
public void Delete(IEnumerable<T> listo)
{
using (var context = getInstence())
{
foreach (T o in listo)
{
object original = context.GetObjectByKey(o.EntityKey);
context.DeleteObject(o);
}
context.SaveChanges();
}
}

}

public class DataService
{
/// <summary>
/// 设置从配置文件中读取的ObjectContext节点\n默认为"EFObjectContext"
/// </summary>
public static string EFObjectContext = "EFObjectContext";
/// <summary>
/// 设置从配置文件中读取的EF链接节点\n默认为"ConnectionString"
/// </summary>
public static string ConnectionString = "ConnectionString";
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: