EFCore中实体映射与使用sql语句的增删改查方法汇总

2020-04-02  本文已影响0人  林间树洞
EF Core 是一个ORM(对象关系映射),它使 .NET 开发人员可以使用 .NET对象操作数据库,避免了像ADO.NET访问数据库的代码,开发者只需要编写对象即可。使用对象通过EF Core提供的实体映射方法便可以简易实现增删改查。

实体映射方法:

  public class LinqDao<T> : ILinqDao<T> where T : class
    {
        private DataContext db;

        public LinqDao(DataContext _db)
        {
            _db.Database.SetCommandTimeout(10);

            db = _db;       
        }

        /// <summary>
        /// 异步执行增加操作以及返回带有输出的参数
        /// </summary>
        /// <param name="Entity"></param>
        /// <returns></returns>
        public async Task<bool> Add(T Entity)
        {
            await db.Set<T>().AddAsync(Entity);
            return await db.SaveChangesAsync() > 0;
        }

        /// <summary>
        ///  异步执行删除操作以及返回带有输出的参数
        /// </summary>
        /// <param name="Entity"></param>
        /// <returns></returns>
        public async Task<bool> Delete(T Entity)
        {
            db.Set<T>().Remove(Entity);
            return await db.SaveChangesAsync() > 0;
        }

        /// <summary>
        ///  异步执行修改操作以及返回带有输出的参数
        /// </summary>
        /// <param name="Entity"></param>
        /// <returns></returns>
        public async Task<bool> Update(T Entity)
        {
            db.Set<T>().Update(Entity);

            return await db.SaveChangesAsync() > 0;
        }

        /// <summary>
        ///  执行查询操作以及返回实体集合
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IEnumerable<T> GetEntities(Expression<Func<T, bool>> exp)
        {
            return CompileQuery(exp);
        }

        /// <summary>
        ///  执行查询操作以及按照查询条件返回对应的实体集合
        /// </summary>
        /// <param name="Page"></param>
        /// <param name="pageSize"></param>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IEnumerable<T> GetEntitiesForPaging(int Page, int pageSize, Expression<Func<T, bool>> exp)
        {
            return CompileQuery(exp).Skip((Page - 1) * pageSize).Take(pageSize);
        }

        /// <summary>
        ///  执行查询与排序操作以及返回单个实体
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public T GetEntityOrderBy<IKey>(Expression<Func<T, bool>> exp, Expression<Func<T, IKey>> orderBy)
        {
            return CompileQuerySingle(exp, orderBy);
        }


        /// <summary>
        ///  执行查询操作以及返回单个实体
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public T GetEntity(Expression<Func<T, bool>> exp)
        {
            return CompileQuerySingle(exp);
        }


        /// <summary>
        ///  执行查询操作以及按照组合表达式返回对应的实体集合
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        private IEnumerable<T> CompileQuery(Expression<Func<T, bool>> exp)
        {
            var func = EF.CompileQuery((DataContext context, Expression<Func<T, bool>> exps) => context.Set<T>().Where(exp));
            return func(db, exp);
        }

        /// <summary>
        /// 执行查询与排序操作以及按照组合表达式返回对应的单个实体
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        private T CompileQuerySingle<IKey>(Expression<Func<T, bool>> exp, Expression<Func<T, IKey>> orderBy)
        {

            var func = EF.CompileQuery((DataContext context, Expression<Func<T, bool>> exps) => context.Set<T>().OrderByDescending(orderBy).FirstOrDefault(exp));
            return func(db, exp);
        }


        /// <summary>
        /// 执行查询操作以及按照组合表达式返回对应的单个实体
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        private T CompileQuerySingle(Expression<Func<T, bool>> exp)
        {

            var func = EF.CompileQuery((DataContext context, Expression<Func<T, bool>> exps) => context.Set<T>().FirstOrDefault(exp));
            return func(db, exp);
        }

    }
}

上述方法的原文链接

使用linq的组合表达式可以应付大部分数据库操作,为此把部分拼接条件的实现封装起来。
public static class LinqBuilder
{
    /// <summary>
    /// 默认True条件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static Expression<Func<T, bool>> True<T>() { return f => true; }

    /// <summary>
    /// 默认False条件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static Expression<Func<T, bool>> False<T>() { return f => false; }

    /// <summary>
    /// 拼接 OR 条件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="exp"></param>
    /// <param name="condition"></param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> exp, Expression<Func<T, bool>> condition)
    {
        var inv = Expression.Invoke(condition, exp.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.Or(exp.Body, inv), exp.Parameters);
    }

    /// <summary>
    /// 拼接And条件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="exp"></param>
    /// <param name="condition"></param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> exp, Expression<Func<T, bool>> condition)
    {
        var inv = Expression.Invoke(condition, exp.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.And(exp.Body, inv), exp.Parameters);
    }
}

使用实体映射方法虽简便,但不足以应付各种事务,还是需要使用存储过程,以下是调用存储过程的方法。

public class SqlDao<T> : ISqlDao<T> where T : class
{
    private DataContext db;

    public SqlDao(DataContext _db)
    {
        _db.Database.SetCommandTimeout(3);

        db = _db;
    }

    /// <summary>
    /// 执行存储过程方法 获取实体集合以及返回空值处理
    /// </summary>
    /// <param name="db"></param>
    /// <param name="sql"></param>
    /// <param name="sqlParams"></param>
    /// <returns></returns>
    public async Task<List<T>> GetEntitiesAsync(string sql, MySqlParameter[] sqlParams = null)
    {
        var connection = db.Database.GetDbConnection();
        using (var cmd = connection.CreateCommand())
        {
            await db.Database.OpenConnectionAsync();
            cmd.CommandText = sql;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            if (sqlParams != null)
            {
                cmd.Parameters.AddRange(sqlParams);
            }

            var dr = await cmd.ExecuteReaderAsync();
            var columnSchema = dr.GetColumnSchema();
            var data = new List<T>();
            while (await dr.ReadAsync())
            {
                // T t = System.Activator.CreateInstance<T>();
                Type type = typeof(T);
                //  创建一个类T的实例
                object entity = type.Assembly.CreateInstance(type.FullName);
                // 得到类T的名称(不包含命名空间)
                string name = type.Name;
                // 获取类T的所有属性
                PropertyInfo[] props = type.GetProperties();
                
                for (int i = 0; i < columnSchema.Count; i++)
                {
                    var kv = columnSchema[i];
                    if (kv.ColumnOrdinal.HasValue)
                    {
                        var itemVal = dr.GetValue(kv.ColumnOrdinal.Value);
                        var Value = itemVal.GetType() != typeof(DBNull) ? itemVal : null;

                        Type TypeDefinition = (props[i].PropertyType == typeof(int?)) ? typeof(int) : props[i].PropertyType;

                        //Type TypeDefinition = Nullable.GetUnderlyingType(props[i].PropertyType);
                        object o = (Value == null) ? null : Convert.ChangeType(Value, TypeDefinition, null);

                        props[i].SetValue(entity, o, null);
                    }
                }
                data.Add((T)entity);
            }
            dr.Dispose();
            return data.Count < 1 ? null : data;
        }
    }


    /// <summary>
    /// 执行带有参数的存储过程方法 获取信息集合以及返回空值处理
    /// </summary>
    /// <param name="db"></param>
    /// <param name="sql"></param>
    /// <param name="sqlParams"></param>
    /// <returns></returns>
    public async Task<T> GetEntityAsync(string sql, MySqlParameter[] sqlParams=null)
    {
        var connection = db.Database.GetDbConnection();
        using (var cmd = connection.CreateCommand())
        {
            await db.Database.OpenConnectionAsync();
            cmd.CommandText = sql;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            if (sqlParams != null)
            {
                cmd.Parameters.AddRange(sqlParams);
            }

            var dr = await cmd.ExecuteReaderAsync();
            var columnSchema = dr.GetColumnSchema();
            var data = new List<T>();

            while (await dr.ReadAsync())
            {
                // T t = System.Activator.CreateInstance<T>();
                Type type = typeof(T);
                //  创建一个类T的实例
                object entity = type.Assembly.CreateInstance(type.FullName);
                // 得到类T的名称(不包含命名空间)
                string name = type.Name;
                // 获取类T的所有属性
                PropertyInfo[] props = type.GetProperties();

                for (int i = 0; i < columnSchema.Count; i++)
                {
                    var kv = columnSchema[i];
                    if (kv.ColumnOrdinal.HasValue)
                    {
                        var itemVal = dr.GetValue(kv.ColumnOrdinal.Value);
                        var Value = itemVal.GetType() != typeof(DBNull) ? itemVal : null;

                        Type TypeDefinition = (props[i].PropertyType == typeof(int?)) ? typeof(int) : props[i].PropertyType;

                        //Type TypeDefinition = Nullable.GetUnderlyingType(props[i].PropertyType);
                        object o = (Value == null) ? null : Convert.ChangeType(Value, TypeDefinition, null);

                        props[i].SetValue(entity, o, null);

                    }
                }
                data.Add((T)entity);
                break;
            }
            dr.Dispose();

            return data.Count < 1 ? null : data[0];

        }
    }

    /// <summary>
    /// 异步执行Sql语句 增删改操作以及返回带有输出的参数
    /// </summary>
    /// <param name="db"></param>
    /// <param name="sql"></param>
    /// <param name="sqlParams"></param>
    /// <returns></returns>
    public async Task<int> ExecuteSqlRawAsync(string sql, MySqlParameter[] sqlParams=null)
    {
        var numint = -1;

        if (sqlParams != null)
        {
             numint = await db.Database.ExecuteSqlRawAsync(sql, sqlParams);
        }
        else
        {
            numint = await db.Database.ExecuteSqlRawAsync(sql);
        }
      

        return numint;
    }



    /// <summary>
    /// 执行存储过程方法 获取信息集合以及返回空值处理
    /// </summary>
    /// <param name="db"></param>
    /// <param name="sql"></param>
    /// <param name="sqlParams"></param>
    /// <returns></returns>
    public async Task<object> GetObjectAsync(string sql, MySqlParameter[] sqlParams=null)
    {
        var connection = db.Database.GetDbConnection();
        using (var cmd = connection.CreateCommand())
        {
            await db.Database.OpenConnectionAsync();
            cmd.CommandText = sql;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            if (sqlParams != null)
            {
                cmd.Parameters.AddRange(sqlParams);
            }

            var result = await cmd.ExecuteScalarAsync();

            if (result == null)
            {
                return null;
            }

            return result;
        }
    }
}

ps:使用EFCore方法时,需要注意返回值的类型,是否跟实体映射的非空类型冲突。

上一篇 下一篇

猜你喜欢

热点阅读