最近使用Entity Framework 开发,分享一下这次使用的心得。这次的开发时间比较少,代码有些粗糙,请大家包涵。
1、多一点使用 IQueryable,少一点使用 IEnumerable。因为使用IQueryable 可以看到实际执行的sql语句,而且在动态排序、动态条件查询上容易得多。
2、动态条件查询
/// <summary>
/// 查询条件
/// </summary>
/// <param name="source">对象</param>
/// <param name="yhm">用户名</param>
/// <param name="xm">姓名</param>
/// <returns></returns>
public IQueryable<YHJBXX> getCondition(IQueryable<YHJBXX> source, string yhm, string xm)
{
var condi = source;
if (!string.IsNullOrWhiteSpace(yhm))
{
condi = condi.Where(t => t.YHM != null && t.YHM.Contains(yhm));
}
if (!string.IsNullOrWhiteSpace(xm))
{
condi = condi.Where(t => t.XM != null && t.XM.Contains(xm));
}
return condi;
}
3、动态排序。这里要先加一个设置排序的公用类LinqTools,getOrder<T>方法是外部调用用于排序的。QueryableExtensions类是在网上抄的,用途就是动态排序
class LinqTools
{
private static object GetPropertyValue(object obj, string property)
{
System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(property);
return propertyInfo.GetValue(obj, null);
}
private static string[] getkv(string str)
{
if (string.IsNullOrEmpty(str))
{
return new string[2]{"",""};
}
else
{
int idx = str.IndexOf(" ");
if (idx < 0)
{
return new string[2]{str, ""};
}
else
{
return new string[2]{str.Substring(0, idx), str.Substring(idx + 1)};
}
}
}
public static IQueryable<T> getOrder<T>(IQueryable<T> query, string orderby)
{
if (!string.IsNullOrEmpty(orderby))
{
List<string[]> lst = new List<string[]>();
//排序的列
foreach (var item in orderby.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
lst.Add(getkv(item));
}
if (lst.Count > 0)
{
IOrderedQueryable<T> order = null;
if (lst[0][1].ToLower() == "desc")
{
order = QueryableExtensions.OrderBy<T>(query, lst[0][0],true);
}
else
{
order = QueryableExtensions.OrderBy<T>(query, lst[0][0]);
}
//多列排序
for (int i = 1; i < lst.Count; i++)
{
if (lst[i][1].ToLower() == "desc")
{
order = QueryableExtensions.ThenBy(order, lst[i][0],true);
}
else
{
order = QueryableExtensions.ThenBy(order, lst[i][0]);
}
}
query = order.AsQueryable();
}
}
return query;
}
}
public static class QueryableExtensions
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> queryable, string propertyName)
{
return OrderBy(queryable, propertyName, false);
}
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> queryable, string propertyName, bool desc)
{
var param = Expression.Parameter(typeof(T));
var body = Expression.Property(param, propertyName);
dynamic keySelector = Expression.Lambda(body, param);
return desc ? Queryable.OrderByDescending(queryable, keySelector) : Queryable.OrderBy(queryable, keySelector);
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> queryable, string propertyName)
{
return ThenBy(queryable, propertyName, false);
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> queryable, string propertyName, bool desc)
{
var param = Expression.Parameter(typeof(T));
var body = Expression.Property(param, propertyName);
dynamic keySelector = Expression.Lambda(body, param);
return desc ? Queryable.ThenByDescending(queryable, keySelector) : Queryable.ThenBy(queryable, keySelector);
}
}
4、动态查询、动态排序、动态分页
public List<YHJBXX> getDataWithPage(string yhm,string xm,string orderby,int pageindex,int pagesize)
{
using (ZJHMDEntities ctx = new ZJHMDEntities())
{
var condi = getCondition(ctx.YHJBXX, yhm, xm);
var order = LinqTools.getOrder<YHJBXX>(condi, orderby);
var skip = order.Skip(pagesize * (pageindex - 1)).Take(pagesize);
return skip.ToList();
}
}
需要说一下的是,这里排序是必须的,否则到了skip这个方法的时候会提示错误的,其实不排序也可以分页的,自己改改代码,这里就不说了。
5、加密数据库连接字符串。ZJHMDModel.edmx 我的一个ado.net实体 ,里面有一个ZJHMDModel.Context.tt 的文件,ZJHMDModel.Context.cs里,
public ZJHMDEntities()
: base("name=ZJHMDEntities")
{
this.Database.Connection.ConnectionString = ZJHMDSettings.connectstr;
}
ZJHMDSettings.connectstr 是我解密后的字符串,建议这个字符串设置成只读,否则每一次访问数据库都调用一次解密方法,性能是有损耗的而且没有必要。
注意的,每次edmx文件每次重新生成的时候,这个方法都会被重置,暂时没有更好的办法。
6、自动递增ID的获取方法。很多时候我们用了oracle的触发器,在新建记录时,自动填入序号到ID里,ado.net 实例该如何获取加入记录后的ID号呢。答案如下,在edmx文件里,设置列的StoreGeneratePattern属性为 Identity,保存记录后,ID列自然就可以获取到相应的值了。
7、强制执行更新操作。一般情况下,我们会先找到这条记录,然后更改,最后就保存。
public void loginSucc(string yhm)
{
using (ZJHMDEntities ctx = new ZJHMDEntities())
{
YHJBXX obj = ctx.YHJBXX.FirstOrDefault(t => t.YHM == yhm);
obj.ZJDLSJ = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
obj.SCMMCS = 0;
ctx.SaveChanges();
}
}
然而,我们想直接更新某个对象,可以先用Attach方法附加到entities上,然后更改需要保存的字段的状态。如果想整条记录所有列都更新,可以直接赋值
et.State= System.Data.EntityState.Modified;
public int updateYH(YHJBXX yh)
{
int rtv = 0;
using (ZJHMDEntities ctx = new ZJHMDEntities())
{
YHJBXX obj = ctx.YHJBXX.Attach(yh);
var et = ctx.Entry(obj);
//et.State= System.Data.EntityState.Modified;
et.Property("GXSJ").IsModified = true;
et.Property("GXYH").IsModified = true;
et.Property("MM").IsModified = true;
et.Property("XM").IsModified = true;
et.Property("SJHM").IsModified = true;
et.Property("JS").IsModified = true;
et.Property("SCMMCS").IsModified = true;
et.Property("LOCK_FLAG").IsModified = true;
rtv = ctx.SaveChanges();
}
return rtv;
}
这里说的,只是一些很普通的方法,而且只是针对单表操作的,够用就好。