• 我去年写的数据访问层(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
    /// <summary>
    /// EF Transaction Params
    /// </summary>
    /// <typeparam name="TIn1">The type of the in1.</typeparam>
    /// <typeparam name="TOut">The type of the out.</typeparam>
    /// <remarks></remarks>
    public class EFTranParams<TIn1, TOut>
    {
    /// <summary>
    /// 初始化 <see cref="T:System.Object"/> 类的新实例。
    /// </summary>
    /// <remarks></remarks>
    public EFTranParams()
    {
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="EFTranParams<TIn1, TOut>"/> class.
    /// </summary>
    /// <param name="tIn1">The t in1.</param>
    /// <param name="funcName">Name of the func.</param>
    /// <remarks></remarks>
    ,evencolor: #008000;lt;/summary (efParams == t)/span br /ccolor: #808080;/spanolor: #0000ff;T2gt; public EFTranParams(TIn1 tIn1, Func<TIn1, TOut> funcName)
    {
    this.tIn1 = tIn1;
    this.funcName = funcName;
    }
    /// <summary>
    /// Gets or sets the t in1.
    /// </summary>
    /// <value>The t in1.</value>
    /// <remarks></remarks>
    public TIn1 tIn1
    {
    get;
    set;
    }
    /// <summary>
    /// Gets or sets the name of the func.
    /// </summary>
    /// <value>The name of the func.</value>
    /// <remarks></remarks>
    public Func<TIn1, TOut> funcName
    {
    get;
    set;
    }

    /// <summary>
    /// Gets the tuple params.
    /// </summary>
    /// <remarks></remarks>
    internal Tuple<TIn1, Func<TIn1, TOut>> tupleParams
    {
    get
    {
    return Tuple.Create(tIn1, funcName);
    }
    }
    }

     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
    转载请留下原文地址。淘宝男装

  • 相关阅读:
    [转载]C# TCP实现多个客户端与服务端 数据 与 文件的传输
    【转载】心跳机制
    paip.web数据绑定 下拉框的api设计 选择框 uapi python .net java swing jsf总结
    paip.复制文件 文件操作 api的设计uapi java python php 最佳实践
    paip.php 与js 的相似性以及为什么它们这么烂还很流行。。
    paip.重装系统后firefox火狐收藏夹的恢复
    paip.截取字符串byLastDot方法总结uapi python java php c# 总结
    paip.gui控件form窗体的原理实现以及easyui的新建以及编辑实现
    paip.python php的未来预测以及它们的比较优缺点
    paip.快捷方式分组管理最佳实践ObjectDock
  • 原文地址:https://www.cnblogs.com/wmlunge/p/2354401.html
Copyright © 2020-2023  润新知