EF

最近由于公司项目比较忙,本来早就准备写EF部分可是一直没时间,步入正题吧,前一篇讲的是数据访问层中ADO的实现部分,接下来我们讲一下EF部分的实现。

先说一下写他的目的:

  为了使我们在开发中降低程序员的工作量和代码行数,同时提供一个统一格式和便于维护的数据访问调用框架,我们需开发一套数据访问层。

实现功能:

   实现增加、修改、删除、带事务新增、 带事务修改、 带事务删除、分布式事务处理等操作。

实现原理:

  使用新类 EFTranParams(下面提供源码) 构建一个EF事务处理参数,用Action 和Func 将参数传递给数据访问层,已委托的方式在事务中执行相关的方法,返回处理结果。

代码实现:

    基本的EF扩展方法:

View Code
 

   再看看EF部分带事务处理的部分代码:

View Code
#region EF Tran Function

/// <summary>
/// Inserts the model with transaction.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context">The context.</param>
/// <param name="obj">The obj.</param>
/// <returns></returns>
/// <remarks></remarks>
public static Int32 InsertModelWithTransaction<T>(this ObjectContext context, T obj) where T : class
{
return context.ProcModelWithTransaction(obj, ProcType.Insert);
}

/// <summary>
/// Updates the model with transaction.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context">The context.</param>
/// <param name="obj">The obj.</param>
/// <returns></returns>
/// <remarks></remarks>
public static Int32 UpdateModelWithTransaction<T>(this ObjectContext context, T obj) where T : class
{
return context.ProcModelWithTransaction(obj, ProcType.Update);
}

/// <summary>
/// Deletes the model with transaction.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context">The context.</param>
/// <param name="obj">The obj.</param>
/// <returns></returns>
/// <remarks></remarks>
public static Int32 DeleteModelWithTransaction<T>(this ObjectContext context, T obj) where T : class
{
return context.ProcModelWithTransaction(obj, ProcType.Delete);
}

/// <summary>
/// Deletes the model with transaction.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context">The context.</param>
/// <param name="obj">The obj.</param>
/// <returns></returns>
/// <remarks></remarks>
public static Int32 DeleteModelWithTransaction<T>(this ObjectContext context, IEnumerable<T> obj) where T : class
{
return context.DeleteModelList(obj);
}

/// <summary>
/// Procs the model with transaction.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context">The context.</param>
/// <param name="obj">The obj.</param>
/// <param name="ptype">The ptype.</param>
/// <returns></returns>
/// <remarks></remarks>
internal static Int32 ProcModelWithTransaction<T>(this ObjectContext context, T obj, ProcType ptype) where T : class
{
Int32 rValue = 0;
var cnn = (System.Data.EntityClient.EntityConnection)context.Connection;

if (cnn.State == System.Data.ConnectionState.Closed)
{
cnn.Open();
}

System.Data.EntityClient.EntityTransaction transaction = cnn.BeginTransaction();

try
{
switch (ptype)
{
case ProcType.Insert:
rValue = context.InsertModel(obj);
break;
case ProcType.Update:
rValue = context.UpdateModel(obj);
break;
case ProcType.Delete:
rValue = context.DeleteModel(obj);
break;
}
transaction.Commit();
}
catch (Exception f)
{
transaction.Rollback();
throw f;
}
finally
{
cnn.Close();
}
return rValue;
}

/// <summary>
/// Executes the EF with transaction.
/// </summary>
/// <typeparam name="T1">The type of the 1.</typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="context">The context.</param>
/// <param name="efParams">The ef params.</param>
/// <returns></returns>
/// <remarks></remarks>
public static List<TResult> ExecuteEFWithTransaction<T1, TResult>(this ObjectContext context, params EFTranParams<T1, TResult>[] efParams)
{
List<TResult> listObj = new List<TResult>();
var cnn = (System.Data.EntityClient.EntityConnection)context.Connection;

if (cnn.State == System.Data.ConnectionState.Closed)
{
cnn.Open();
}

System.Data.EntityClient.EntityTransaction transaction = cnn.BeginTransaction();

try
{
if (efParams == null)
{
throw new ArgumentNullException("efParams is null");
}

Array
.ForEach<EFTranParams<T1, TResult>>
(efParams, t => listObj.Add(t.tupleParams.Item2(t.tupleParams.Item1)));
transaction.Commit();
}
catch (Exception f)
{
transaction.Rollback();
throw f;
}
finally
{
if (context.Connection.State == System.Data.ConnectionState.Open)
{
context.Connection.Close();
}
}
return listObj;
}

/// <summary>
/// Executes the EF with transaction.
/// </summary>
/// <typeparam name="T1">The type of the 1.</typeparam>
/// <typeparam name="T2">The type of the 2.</typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="context">The context.</param>
/// <param name="efParams">The ef params.</param>
/// <returns></returns>
/// <remarks></remarks>
public static List<TResult> ExecuteEFWithTransaction<T1, T2, TResult>(this ObjectContext context, params EFTranParams<T1, T2, TResult>[] efParams)
{
List<TResult> listObj = new List<TResult>();
var cnn = (System.Data.EntityClient.EntityConnection)context.Connection;

if (cnn.State == System.Data.ConnectionState.Closed)
{
cnn.Open();
}

System.Data.EntityClient.EntityTransaction transaction = cnn.BeginTransaction();

try
{
if (efParams == null)
{
throw new ArgumentNullException("efParams is null");
}

Array.ForEach<EFTranParams<T1, T2, TResult>>(efParams, t => listObj.Add(t.tupleParams.Item3(t.tupleParams.Item1, t.tupleParams.Item2)));
transaction.Commit();
}
catch (Exception f)
{
transaction.Rollback();
throw f;
}
finally
{
if (context.Connection.State == System.Data.ConnectionState.Open)
{
context.Connection.Close();
}
}
return listObj;
}

/// <summary>
/// Executes the EF with transaction.
/// </summary>
/// <typeparam name="T1">The type of the 1.</typeparam>
/// <typeparam name="T2">The type of the 2.</typeparam>
/// <typeparam name="T3">The type of the 3.</typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="context">The context.</param>
/// <param name="efParams">The ef params.</param>
/// <returns></returns>
/// <remarks></remarks>
public static List<TResult> ExecuteEFWithTransaction<T1, T2, T3, TResult>(this ObjectContext context, params EFTranParams<T1, T2, T3, TResult>[] efParams)
{
List<TResult> listObj = new List<TResult>();
var cnn = (System.Data.EntityClient.EntityConnection)context.Connection;

if (cnn.State == System.Data.ConnectionState.Closed)
{
cnn.Open();
}

System.Data.EntityClient.EntityTransaction transaction = cnn.BeginTransaction();

try
{
if (efParams == null)
{
throw new ArgumentNullException("efParams is null");
}

Array.ForEach<EFTranParams<T1, T2, T3, TResult>>(efParams, t => listObj.Add(t.tupleParams.Item4(t.tupleParams.Item1, t.tupleParams.Item2, t.tupleParams.Item3)));
transaction.Commit();
}
catch (Exception f)
{
transaction.Rollback();
throw f;
}
finally
{
if (context.Connection.State == System.Data.ConnectionState.Open)
{
context.Connection.Close();
}
}
return listObj;
}

/// <summary>
/// Executes the EF with transaction.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="action">The action.</param>
/// <remarks></remarks>
public static void ExecuteEFWithTransaction(this ObjectContext context, Action action)
{
var cnn = (System.Data.EntityClient.EntityConnection)context.Connection;

if (cnn.State == System.Data.ConnectionState.Closed)
{
cnn.Open();
}

System.Data.EntityClient.EntityTransaction transaction = cnn.BeginTransaction();

try
{
action();
transaction.Commit();
}
catch (Exception f)
{
transaction.Rollback();
throw f;
}
finally
{
if (context.Connection.State == System.Data.ConnectionState.Open)
{
context.Connection.Close();
}
}
}

#endregion

   EFTanParams.cs的代码:

View Code

 EF扩展方法中用到的扩展方法

View Code
/// <summary>
/// Attaches the existed entity.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="context">The context.</param>
/// <param name="entity">The entity.</param>
/// <returns></returns>
/// <remarks></remarks>
internal static void AttachExistedEntity<TEntity>(this ObjectContext context, TEntity entity)
where TEntity : class
{
string entitySetName = context.GetEntityName<TEntity>();
ObjectStateEntry stateEntry = null;
if (entity is EntityObject && (entity as EntityObject).EntityKey != null)
{
if (!context.ObjectStateManager.TryGetObjectStateEntry((entity as EntityObject).EntityKey, out stateEntry))
{
context.Attach(entity as EntityObject);
}
}
else
{
context.AttachTo(entitySetName, entity);
}
}

///// <summary>
///// Gets the name of the entity.
///// </summary>
///// <typeparam name="TEntity"></typeparam>
///// <returns></returns>
///// <remarks></remarks>
internal static string GetEntityName<TEntity>(this ObjectContext context)
{
string className = typeof(TEntity).Name;
var container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
string entitySetName = (from meta in container.BaseEntitySets
where meta.ElementType.Name == className
select meta.Name).First();
return entitySetName;
}

 使用方法:

View Code
public sending p_sending = null;
public IList<sending_detail> p_sending_detailList = null;

public void InsertSend(sending obj) {

context.InsertModelWithTransaction<sending>(obj);
}

public void UpdateSend(sending obj) {
context.UpdateModelWithTransaction<sending>(obj);
}

public void InsertSend_A(sending obj) {
context.sending.AddObject(obj);
context.SaveChanges();
}

private string DeleteSendDetail(sending obj) {

context.DeleteModelList<sending_detail>(obj.sending_detail.ToList<sending_detail>());
//Delete<sending>(obj);

context.DeleteModelWithTransaction<sending>(obj);

return "";
}

public void DeleteSend_A(sending obj) {

var t = new Bridgetree.DBAccess.EFTranParams<sending, string>();

t.tIn1 = obj;
t.funcName = DeleteSendDetail;

context.ExecuteEFWithTransaction(t);

/*
using (var scope = new TransactionScope()) {

try {
DeleteList<sending_detail>(obj.sending_detail.ToList<sending_detail>());
Delete<sending>(obj);

//DeleteModel<sending>(obj);

scope.Complete();
}
catch (Exception f) {
throw f;
}
}
*/
}


private void UpdateSendDetail() {

context.UpdateModel<sending>(p_sending);
//UpdateByPriId<sending>(p_sending, "sending_id", p_sending.sending_id);

context.DeleteByField<sending_detail>(p_sending.sending_id, "sending_id");

sending_detail mysending_detail = null;
foreach (sending_detail obj in p_sending_detailList) {
mysending_detail = new sending_detail();

new Bridgetree.DBAccess.Utility().SetObjToEntity<sending_detail, sending_detail>(obj, mysending_detail, "sending_detail_id");
mysending_detail.sending_id = p_sending.sending_id;
context.InsertModel<sending_detail>(mysending_detail);
}
}

public void UpdateSend_A() {

Action a = UpdateSendDetail;

context.ExecuteEFWithTransaction(a);
}

public sending GetsendingByid_A(int id) {

IList<sending> myList = (

from r in context.sending
where r.sending_id == id
select r
).ToList<sending>();

if (myList.Count > 0) {
return myList[0];
}
else {
return null;
}
}

public sending GetsendingByid(int id) {
var mysending = context
.sending
.Where(s=>s.sending_id==id)
.FirstOrDefault();

return mysending;
}

 下一篇讲一下表单的自动填写和数据访问层里的其他方法。

  源码下载地址:点击下载

  帮助文档下载地址:点击下载 

  测试项目:点击下载 

文章出处:http://www.cnblogs.com/wmlunge/archive/2012/02/16/2354401.html

原文地址:https://www.cnblogs.com/wichell/p/2354442.html