下面是关键的实现代码,由于有注释我不再赘述:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects.DataClasses; using System.Data; using System.Data.EntityClient; using System.Data.Metadata.Edm; using System.Data.Mapping; using System.Reflection; using System.Collections; using System.Threading; using System.Data.Objects; using System.Runtime.Serialization; using System.Configuration; using System.Data.Common; using System.Linq.Expressions; namespace EFLabModelFirst.JT.Dao { public delegate object EFCallBackHandler(ObjectContext em); public delegate TResult EFSelectCallBackHandler<IQueryable, TResult>(IQueryable query); /// <summary> /// 摘要: /// Entity Framework封装类,简化访问 /// 请不要随意修改这个类 /// xxx.Config参考配置: /// <configuration> /// <appSettings> /// <!--连接字符串的名称--> /// <add key="ConnectionStringKey" value="modelfirstEntities"/> /// <!--实体容器的名称--> /// <add key="EntityContainerName" value="modelfirstEntities"/> /// <!--对象上下文类型--> /// <add key="ObjectContextType" value="EFLabModelFirst.modelfirstEntities"/> /// </appSettings> /// <connectionStrings> /// <add name="modelfirstEntities" connectionString="metadata=res://*/ModelFirst.csdl|res://*/ModelFirst.ssdl|res://*/ModelFirst.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\sqlexpress;Initial Catalog=modelfirst;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" /> /// </connectionStrings> /// </configuration> /// </summary> public class DaoTemplate { [ThreadStatic] private static ObjectContext _em = null; /// <summary> /// 对象上下文,每个线程访问该属性可以获得一个单独的实例 /// </summary> private static ObjectContext EM { get { if (_em == null) { try { _em = Activator.CreateInstance(Type.GetType(ObjectContextType), ConfigurationManager.ConnectionStrings[ConnectionStringKey].ConnectionString, EntityContainerName) as ObjectContext; } catch (Exception ex) { throw new Exception("创建ObjectContext失败,可能是在模型代码后置文件\"xxx.Designer.cs\"里面没有找到需要手动添加的构造函数,比如:public modelfirstEntities(string connectionString,string defaultContainerName):base(connectionString,defaultContainerName)",ex); } if (_em == null) throw new Exception("创建ObjectContext失败,原因不明"); } return _em; } } /// <summary> /// 连接字符串key /// </summary> static readonly string ConnectionStringKey = string.Empty; /// <summary> /// 实体容器名称 /// </summary> static readonly string EntityContainerName = string.Empty; /// <summary> /// 对象上下文名称 /// </summary> static readonly string ObjectContextType = string.Empty; /// <summary> /// 存储所有实体类名和实体集名称的映射 /// Key:实体类型名称 /// Value:实体集名称 /// </summary> public static readonly Dictionary<String, String> EntitySetNameMap = new Dictionary<String, String>(); /// <summary> /// 静态代码块,所有线程执行前该方法有且仅有执行一次 /// </summary> static DaoTemplate() { ObjectContextType = ConfigurationManager.AppSettings["ObjectContextType"]; ConnectionStringKey = ConfigurationManager.AppSettings["ConnectionStringKey"]; EntityContainerName = ConfigurationManager.AppSettings["EntityContainerName"]; if (string.IsNullOrEmpty(ObjectContextType)) throw new Exception("xxx.Config文件\"appSettings节\"没有配置ObjectContext"); if (string.IsNullOrEmpty(ConnectionStringKey)) throw new Exception("xxx.Config文件\"connectionStrings节\"没有配置连接字符串"); if (string.IsNullOrEmpty(EntityContainerName)) throw new Exception("xxx.Config文件\"appSettings节\"没有配置实体容器名称"); //构建连接对象 EntityConnectionStringBuilder ecsb = new EntityConnectionStringBuilder(ConfigurationManager.ConnectionStrings[ConnectionStringKey].ConnectionString); string[] arrstr = ecsb.Metadata.Split('|');//得到映射文件 EdmItemCollection e = new EdmItemCollection(arrstr[0]);//得到CSDL StoreItemCollection s = new StoreItemCollection(arrstr[1]);//得到SSDL StorageMappingItemCollection smt = new StorageMappingItemCollection(e, s, arrstr[2]);//得到MSL //获取合部实体对应关系 var entities = smt[0].GetType().GetProperty("EntitySetMaps", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(smt[0], null); //反射得到StorageSetMapping类型 Assembly ass = Assembly.Load("System.Data.Entity,Version=3.5.0.0,culture=Neutral,PublicKeyToken=b77a5c561934e089"); Type type = ass.GetType("System.Data.Mapping.StorageSetMapping"); foreach (var entityvalue in (IList)entities) { var p = entityvalue.GetType().GetField("m_extent", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); EntitySet es = (EntitySet)type.GetField("m_extent", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entityvalue); EntitySetNameMap.Add(es.ElementType.Name, es.Name); } } /// <summary> /// 提交保存 /// </summary> public void Commit() { EM.SaveChanges(); } /// <summary> /// 获得一个实体的主键名称 /// </summary> /// <param name="entityType">实体类的类型信息对象</param> /// <returns>主键名称</returns> public virtual string GetKeyName(Type entityType) { foreach (var pi in entityType.GetProperties()) { var attr = pi.GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).FirstOrDefault() as EdmScalarPropertyAttribute; if (attr != null && pi.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault() != null && attr.EntityKeyProperty) return pi.Name; } return string.Empty; } /// <summary> /// 添加一个对象 /// </summary> /// <param name="obj">待添加的对象</param> public virtual void AddObject(Object obj) { EM.AddObject(EntitySetNameMap[obj.GetType().Name], obj); EM.SaveChanges(); } /// <summary> /// 删除一个对象 /// </summary> /// <param name="obj">待删除的对象</param> public virtual void DeleteObject(Object obj) { EM.AttachTo(EntitySetNameMap[obj.GetType().Name], obj); EM.DeleteObject(obj); EM.SaveChanges(); } /// <summary> /// 获得一个实体 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="keyValue">主键值</param> /// <returns>查询到的对象</returns> public virtual T GetEntityByKey<T>(object keyValue) where T : class { return EM.GetObjectByKey(new EntityKey(EntityContainerName + "." + EntitySetNameMap[typeof(T).Name], GetKeyName(typeof(T)), keyValue)) as T; } /// <summary> /// 根据条件获取某个对象 /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="where">查询条件</param> /// <returns>实体</returns> public virtual T GetEntity<T>(Expression<Func<T, bool>> where) where T : class { return EM.CreateObjectSet<T>().Where(where).FirstOrDefault(); } /// <summary> /// 该函数已过期,根据条件获取某个值,比如聚合函数查询, /// </summary> /// <typeparam name="T">类型</typeparam> /// <typeparam name="TResult">查询结果了性</typeparam> /// <param name="where">查询条件</param> /// <param name="selector">投影表达式树</param> /// <returns></returns> //public virtual TResult GetObject<T, TResult>(Expression<Func<T, bool>> where, Expression<Func<T, TResult>> selector) where T : class //{ // return EM.CreateObjectSet<T>().Where<T>(where).Select<T, TResult>(selector).FirstOrDefault<TResult>(); //} /// <summary> /// 根据条件获取某个值,比如聚合函数查询 /// </summary> /// <typeparam name="T">被查询的类型</typeparam> /// <typeparam name="TResult">查询结果类型</typeparam> /// <param name="where">查询条件</param> /// <param name="includes">要抓取的导航属性数组</param> /// <param name="selectHandler">投影委托</param> /// <returns>查询结果</returns> public virtual TResult GetObject<T, TResult>(EFSelectCallBackHandler<IQueryable<T>, TResult> selectHandler,Expression<Func<T, bool>> where, params string[] includes) where T : class { if (selectHandler == null) throw new Exception("委托EFSelectCallBackHandler不能为空"); IQueryable<T> query = EM.CreateObjectSet<T>(); if (includes == null || includes.Length == 0) query = query.Where<T>(where == null ? t => true : where); else { foreach (var include in includes) { if (string.IsNullOrEmpty(include)) continue; query = (query as ObjectQuery<T>).Include(include); } } return selectHandler(query); } /// <summary> /// 根据条件获取某个值,比如聚合函数查询 /// </summary> /// <typeparam name="T">被查询的类型</typeparam> /// <typeparam name="TResult">查询结果类型</typeparam> /// <param name="includes">要抓取的导航属性数组</param> /// <param name="selectHandler">投影委托</param> /// <returns>查询结果</returns> public virtual TResult GetObject<T, TResult>(EFSelectCallBackHandler<IQueryable<T>, TResult> selectHandler,params string[] includes) where T : class { return GetObject<T, TResult>(selectHandler, null, includes); } /// <summary> /// 根据实体的实体键修改实体 /// </summary> /// <param name="obj"></param> public virtual void UpdateObject(object obj) { EM.AttachTo(EntitySetNameMap[obj.GetType().Name], obj); EM.ObjectStateManager.ChangeObjectState(obj, EntityState.Modified); EM.SaveChanges(); } /// <summary> /// 根据条件进行查询 /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="where">查询条件</param> /// <returns>符号条件的实体的集合</returns> public ICollection<T> FindList<T>(Func<T, bool> where) where T : class { return EM.CreateObjectSet<T>().Where<T>(where).AsEnumerable().ToList(); } /// <summary> /// 根据多个条件进行查询 /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="where">查询条件</param> /// <returns>符合条件的实体的集合</returns> public ICollection<T> FindList<T>(params Func<T, bool>[] where) where T : class { if (where != null && where.Length > 0) { IEnumerable<T> query = EM.CreateObjectSet<T>().Where(where[0]); for (int i = 1; i < where.Length; i++) { query = query.Where(where[i]); } return query.ToList<T>(); } return null; } /// <summary> /// 根据条件、排序、投影进行查找 /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <typeparam name="TKey">排序属性类型</typeparam> /// <typeparam name="TResult">返回结果类型</typeparam> /// <param name="where">查询条件树</param> /// <param name="orderSelector">排序</param> /// <param name="selector">投影</param> /// <returns>符合条件的对象的集合</returns> public ICollection<TResult> FindList<T, TKey, TResult>(Expression<Func<T, bool>> where, Func<T, TKey> orderSelector, Func<T, TResult> selector) where T : class { return EM.CreateObjectSet<T>().Where<T>(where).OrderBy(orderSelector).Select(selector).ToList(); } /// <summary> /// 根据条件和排序进行查找,带抓取功能 /// </summary> /// <typeparam name="T">被查询的实体类型</typeparam> /// <typeparam name="TKey">排序属性的类型</typeparam> /// <typeparam name="TResult">查询结果类型</typeparam> /// <param name="where">查询条件</param> /// <param name="include">抓取属性</param> /// <param name="orderSelector">排序选择器</param> /// <param name="selector">投影选择器</param> /// <returns></returns> public ICollection<TResult> FindList<T, TKey, TResult>(Expression<Func<T, bool>> where,string include,Func<T, TKey> orderSelector, Func<T, TResult> selector) where T : class { return EM.CreateObjectSet<T>().Include(include).Where<T>(where).OrderBy(orderSelector).Select(selector).ToList(); } /// <summary> /// 执行原始SQL查询 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="commandText">要执行查询的SQL语句</param> /// <param name="parameters">参数</param> /// <returns>符合条件的对象的集合</returns> public ICollection<T> ExecuteSqlQuery<T>(string commandText,params DbParameter[] parameters) { return EM.ExecuteStoreQuery<T>(commandText, parameters).ToList<T>(); } /// <summary> /// 执行原始SQL命令 /// </summary> /// <param name="commandText">SQL命令</param> /// <param name="parameters">参数</param> /// <returns>影响的记录数</returns> public int ExecuteSqlNonQuery(string commandText, params DbParameter[] parameters) { return EM.ExecuteStoreCommand(commandText, parameters); } /// <summary> /// 执行任何操作 /// </summary> /// <param name="callBackHandler"></param> /// <returns></returns> protected object Execute(EFCallBackHandler callBackHandler) { return callBackHandler(EM); } /// <summary> /// 分页泛型方法 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="Tkey"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="pi"></param> public void Pager<T,Tkey,TResult>(PageInfo<T,Tkey,TResult> pi) where T:class { ObjectSet<T> os = EM.CreateObjectSet<T>(); IQueryable<T> query = null; if (!string.IsNullOrEmpty(pi.Include)) query = os.Include(pi.Include); else query = os.AsQueryable<T>(); query = query.Where<T>(pi.Where == null ? t => true : pi.Where); //总条数 pi.RecordCount = query.LongCount(); //总页数 pi.PageCount = pi.RecordCount % pi.PageSize == 0 ? pi.RecordCount / pi.PageSize : pi.RecordCount / pi.PageSize + 1; query = query .OrderBy<T, Tkey>(pi.Order == null ? t => default(Tkey) : pi.Order) .Skip<T>((pi.PageIndex - 1) * pi.PageSize) .Take<T>(pi.PageSize); if (pi.Select != null) pi.List = query.Select<T, TResult>(pi.Select).ToList<TResult>(); else pi.List = query.ToList<T>() as ICollection<TResult>; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SqlClient; using System.Linq.Expressions; namespace EFLabModelFirst.JT.Dao { /// <summary> /// 有关于出版社的查询示范, /// </summary> public class PublisherDao:DaoTemplate { /// <summary> /// sql查询 /// </summary> public void Find1() { ICollection<Publisher> plist = ExecuteSqlQuery<Publisher>("SELECT * FROM Publishers AS P WHERE SUBSTRING(P.PublisherName,LEN(P.PublisherName)-2,3)=@Suffix", new SqlParameter("@Suffix", "出版社")); foreach (var item in plist) { Console.WriteLine(item.PublisherID+"\t"+item.PublisherName); } } /// <summary> /// 手工工造表达式示范 /// </summary> public void Find2() { Expression<Func<int, int, int>> exp1 = (a, b) => a + b * 2; ParameterExpression pexp1 = Expression.Parameter(typeof(int), "a");//参数表达式a ParameterExpression pexp2 = Expression.Parameter(typeof(int), "b");//参数表达式b ConstantExpression cexp = Expression.Constant(2);//常量表达式2 BinaryExpression mutExp = Expression.Multiply(pexp2, cexp);//参数表达式b和常量表达式2相乘的表达式 BinaryExpression addExp = Expression.Add(pexp1, mutExp);//参数表达式1和乘法表达式的求和表达式 Expression<Func<int, int, int>> lambdaExp = Expression.Lambda<Func<int, int, int>>(addExp, pexp1, pexp2);//将求和表达式转换为lambda表达式 Console.WriteLine(lambdaExp); Func<int, int, int> func = lambdaExp.Compile(); Console.WriteLine(exp1.Compile()(100, 60)); Console.WriteLine(func(100, 60)); } /// <summary> /// 该方法没有指定参数将报错 /// </summary> public void Find3() { //BinaryExpression exp1 = Expression.Equal(ConstantExpression.Constant(1),ConstantExpression.Constant(2)); Expression<Func<int, bool>> exp1 = v => v == 2; BinaryExpression exp2 = Expression.And(exp1.Body, ConstantExpression.Constant(true));//没有将exp1转换为调用表达式将报错 Expression<Func<bool>> lamExp = Expression.Lambda<Func<bool>>(exp2); Console.WriteLine(lamExp.Compile()()); } /// <summary> /// 手动构造一个表达式树 /// </summary> public void Find4() { Expression<Func<Publisher, bool>> exp1 = p => p.PublisherName.EndsWith("出版社"); Expression<Func<Publisher, bool>> exp2 = p => p.PublisherID >= 6; ParameterExpression pexp = ParameterExpression.Parameter(typeof(Publisher), "p"); InvocationExpression invokerExp1 = Expression.Invoke(exp1, pexp);//将Lambda表达式exp1应用于参数表达式列表,从而创建一个调用表达式invokerExp1 InvocationExpression invokerExp2 = Expression.Invoke(exp2, pexp);//将Lambda表达式exp2应用于参数表达式列表,从而创建一个调用表达式invokerExp2 BinaryExpression bexp = Expression.And(invokerExp2, invokerExp2); Expression<Func<Publisher, bool>> e = Expression.Lambda<Func<Publisher, bool>>(bexp, pexp); Console.WriteLine(e);//输出这个表达式 var plist = FindList<Publisher>(e.Compile()); foreach (var item in plist) { Console.WriteLine(item.PublisherID+"\t"+item.PublisherName); } } /// <summary> /// 使用PredicateExtensions类提供的扩展方法And构造表达式树 /// </summary> public void Find5() { Expression<Func<Publisher, bool>> exp = p => p.PublisherName.Contains("大学"); exp = exp.And<Publisher>(p => p.PublisherID >= 6); Console.WriteLine(exp); var plist = FindList<Publisher>(exp.Compile()); foreach (var item in plist) { Console.WriteLine(item.PublisherID+"\t"+item.PublisherName); } } /// <summary> /// 使用条件、排序、投影 /// </summary> public void Find6() { var blist = FindList<Book, string, object>( b => b.BookID.StartsWith("ISBN"), b => b.BookID, b => new { b.BookID,b.BookTitle,b.Publisher.PublisherName} ); foreach (var item in blist) { foreach (var pi in item.GetType().GetProperties()) { Console.Write(pi.GetValue(item,null)+"\t"); } Console.WriteLine("\n"); } } public void Find8() { var blist = FindList<Book, string, Book>( b => b.BookID.StartsWith("ISBN"), "Publisher", b => b.BookID, b => new Book{ BookID=b.BookID, BookTitle=b.BookTitle, Publisher=new Publisher{PublisherID=b.PublisherID,PublisherName=b.Publisher.PublisherName} } ); foreach (var item in blist) { Console.WriteLine(item.BookID+"\t"+item.BookTitle+"\t"+item.Publisher.PublisherName); Console.WriteLine("\n"); } } /// <summary> /// 不使用表达式树,传入多个条件表达式实现查询 /// </summary> public void Find7() { var blist = FindList<Book>( b=>b.BookTitle.Contains("设计"), b=>b.BookPrice<=180 ); foreach (var item in blist) { Console.WriteLine(item.BookID+"\t"+item.BookTitle); } } /// <summary> /// 保存书籍 /// </summary> public void Post1() { base.AddObject(new Book { BookID = "ISBN0006",BookTitle="C++Primer", BookDate=DateTime.Now,BookPrice=98,PublisherID=11 }); base.AddObject(new Book { BookID = "ISBN0007", BookTitle = "C++大学教程", BookDate = DateTime.Now.AddYears(-1), BookPrice = 78, PublisherID = 11 }); base.AddObject(new Book { BookID = "ISBN0008", BookTitle = "C和指针", BookDate = DateTime.Now.AddMonths(-7), BookPrice = 88, PublisherID = 11 }); base.Commit(); } } }
代码未经过整理,比较凌乱,由于方法甚至没有使用DaoTemplate的集成