• EF 4.1 一些操作


    1.执行返回表类型的存储过程

    Create PROCEDURE [dbo].[ProSelectStu]
        @StudentID int
    AS
    BEGIN
    
    Select Student.* from Enrollment,Student 
    where Enrollment.StudentID=Student.StudentID
    and Enrollment.StudentID=@StudentID
     
    END
    
    GO

    2.执行返回值的存储过程

    先上存储过程

    CREATE PROCEDURE [dbo].[ProSelectCount]
    @StuId int
    AS
    BEGIN
    select COUNT(*) from Enrollment where StudentID=@StuId
    END

    一个简单的查询数量

    这里用sqlQuery 执行访问 数据库 因为需要提供返回类型 而我们返回的是int 所以先得到int的类型

    CREATE PROCEDURE [dbo].[ProDel]
        @stuId int,
        @courseId int
    AS
    BEGIN
        
        DELETE FROM [WLFSchool].[dbo].[Enrollment] 
        where StudentID=@stuId and CourseID=@courseId
        
    END

    这个用的是操作数据库 返回受影响行数

    三.ef4.1 如何使用数据库视图?每个视图都要去建立对应的实体类么?有简单的方法么?

    先说下最传统的方法 只需把视图 当成表 建立对应的实体类  然后加到dbcontext 里即可。没什么难度。

    再说一个问题 使用linq 有个非常美妙的功能 投影映射 和C#3.0的 匿名函数 让我们很多情况 不需要视图的

    from c in classes
                                      from s in students
                                      where c.ClassID == s.ClassID
                                      order by c.CreateTime
                                      select new
                                      {
                                          Name = s.Name,
                                          Age = s.Age,
                                          ClassName = c.ClassName                                 
                                     };

    再通过  var result 接受上面的值  这样我们就不用去数据库建视图 不用再建实体类 是不是很省事呢?

    如果公司强大的DBA 已经给我们建好了很多视图 是不是就要一个个去写实体类呢?如果你使用的是C#4.0 那么可以用动态的 来解决这个问题~

    像下面这样使用 是不是很爽

    这个不仅可以查询视图 普通的表 只要是SQL语句 都可以自动生成动态类 让你用~

    下面是扩展方法  和 使用Emit 来动态构建 感谢 ASP.NET 韋 给的帮助~~

    SqlQueryForDynamic的扩展方法
    
      public static class DatabaseExtensions
        {
            public static IEnumerable SqlQueryForDynamic(this Database db,
                    string sql,
                    params object[] parameters)
            {
                IDbConnection defaultConn = new System.Data.SqlClient.SqlConnection();
    
                return SqlQueryForDynamicOtherDB(db, sql, defaultConn, parameters);
            }
    
            public static IEnumerable SqlQueryForDynamicOtherDB(this Database db,
                          string sql,
                          IDbConnection conn,
                          params object[] parameters)
            {
                conn.ConnectionString = db.Connection.ConnectionString;
    
                if (conn.State != ConnectionState.Open)
                {
                    conn.Open();
                }
    
                IDbCommand cmd = conn.CreateCommand();
                cmd.CommandText = sql;
    
                IDataReader dataReader = cmd.ExecuteReader();
    
                if (!dataReader.Read())
                {
                    return null; //无结果返回Null
                }
    
                #region 构建动态字段
    
                TypeBuilder builder = DatabaseExtensions.CreateTypeBuilder(
                              "EF_DynamicModelAssembly",
                              "DynamicModule",
                              "DynamicType");
    
                int fieldCount = dataReader.FieldCount;
                for (int i = 0; i < fieldCount; i++)
                {
                    //dic.Add(i, dataReader.GetName(i));
    
                    //Type type = dataReader.GetFieldType(i);
    
                    DatabaseExtensions.CreateAutoImplementedProperty(
                      builder,
                      dataReader.GetName(i),
                      dataReader.GetFieldType(i));
                }
    
                #endregion
    
                dataReader.Close();
                dataReader.Dispose();
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
    
                Type returnType = builder.CreateType();
    
                if (parameters != null)
                {
                    return db.SqlQuery(returnType, sql, parameters);
                }
                else
                {
                    return db.SqlQuery(returnType, sql);
                }
            }
    
            public static TypeBuilder CreateTypeBuilder(string assemblyName,
                                  string moduleName,
                                  string typeName)
            {
                TypeBuilder typeBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                  new AssemblyName(assemblyName),
                  AssemblyBuilderAccess.Run).DefineDynamicModule(moduleName).DefineType(typeName,
                  TypeAttributes.Public);
                typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
                return typeBuilder;
            }
    
            public static void CreateAutoImplementedProperty(
                                TypeBuilder builder,
                                string propertyName,
                                Type propertyType)
            {
                const string PrivateFieldPrefix = "m_";
                const string GetterPrefix = "get_";
                const string SetterPrefix = "set_";
    
                // Generate the field.
                FieldBuilder fieldBuilder = builder.DefineField(
                  string.Concat(
                    PrivateFieldPrefix, propertyName),
                  propertyType,
                  FieldAttributes.Private);
    
                // Generate the property
                PropertyBuilder propertyBuilder = builder.DefineProperty(
                  propertyName,
                  System.Reflection.PropertyAttributes.HasDefault,
                  propertyType, null);
    
                // Property getter and setter attributes.
                MethodAttributes propertyMethodAttributes = MethodAttributes.Public
                  | MethodAttributes.SpecialName
                  | MethodAttributes.HideBySig;
    
                // Define the getter method.
                MethodBuilder getterMethod = builder.DefineMethod(
                    string.Concat(
                      GetterPrefix, propertyName),
                    propertyMethodAttributes,
                    propertyType,
                    Type.EmptyTypes);
    
                // Emit the IL code.
                // ldarg.0
                // ldfld,_field
                // ret
                ILGenerator getterILCode = getterMethod.GetILGenerator();
                getterILCode.Emit(OpCodes.Ldarg_0);
                getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
                getterILCode.Emit(OpCodes.Ret);
    
                // Define the setter method.
                MethodBuilder setterMethod = builder.DefineMethod(
                  string.Concat(SetterPrefix, propertyName),
                  propertyMethodAttributes,
                  null,
                  new Type[] { propertyType });
    
                // Emit the IL code.
                // ldarg.0
                // ldarg.1
                // stfld,_field
                // ret
                ILGenerator setterILCode = setterMethod.GetILGenerator();
                setterILCode.Emit(OpCodes.Ldarg_0);
                setterILCode.Emit(OpCodes.Ldarg_1);
                setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
                setterILCode.Emit(OpCodes.Ret);
    
                propertyBuilder.SetGetMethod(getterMethod);
                propertyBuilder.SetSetMethod(setterMethod);
            }
    
        }

    四.ef4.1 如何执行SQL函数等操作?

    添加引用  System.Data.Objects.SqlClient.SqlFunctions 主要是这个命名空间

    使用方法~上一个工作中的例子~

    var query = from s in student.T_StudentInfo
                            where SqlFunctions.DateDiff("day", s.CreateTime, "2011/11/4") == 0
                            select s.StudentName;

    使用SQL 的datadiff 函数~~

    五.ef4.1 如何跨数据库访问?

    每次别人问我这个问题 毫不犹豫的把站长dudu的文章发过去~ 他已经很好的解决了~

    http://www.cnblogs.com/dudu/archive/2011/03/29/entity_framework_cross_database_query_fact.html

    核心思路 欺骗SQL 利用创建同义词去实现

    六.ef4.1执行连接查询?什么时候执行左连接? 什么时候执行内连接? ef 根据什么去判断?

    当我们做多表查询时  用Include 强制加载 或用 select 去查询时  发现生成的SQL语句 有时是左连接  有时是inner join。

    其实EF是根据我们实体类的连接字段 是否可空来判断的~比如外键 studentID

      public  Nullable<int> StudentID { get; set; }

    是否可空 就会造成 是 left join 还是 inner join~~

    补充下~~ 有个朋友说 这个设为空了 依然执行的是内连接啊~

    注意看下你的关系那块  也要设为可空 用这个   HasOptional 而不要用  HasRequired ~~

    当你的外键可以为空时 用 HasOptional  否则用 HasRequired

    这块也会决定你是内链接 还是 左连接~~


    七.新手使用ef4.1 常见的一些报错信息

    1.执行命令定义时出错

    出现这个错的原因有很多  数据库语句错误 我们可以先通过监测SQL 语句是否发送到数据库 然后执行这条SQL语句 看看是否有问题

     造成这个错的原因 还有可能是 连接对象一直被占用 因为EF有延迟加载 只是select时 并没有真正去数据库执行

    我们可以先把前面的查询语句 tolist等  再去执行下面的操作

    2.

    System.Data.Edm.EdmEntityType: : EntityType“Enrollment”未定义键。请为该 EntityType 定义键。
    System.Data.Edm.EdmEntitySet: EntityType: EntitySet �Enrollments� 基于未定义键的类型 �Enrollment�。

    遇到这种情况 尝试给主键加上[Key]

    3.更新条目错误

    依然检测数据库语句 是否有外键约束导致插入错误等

    4.LINQ to Entities 不识别方法“System.String ToString(System.String)”因此该方法无法转换为存储表达式

      或者不识别其他方法......类似于这样的错误

    因为SQL里没有这样的方法 所以无法转换成SQL语句  SqlClient 和Linq Provider没有实现那个方法对应的SQL,所以会提示不支持

    解决办法:

    1. 把要转换的值提前转换好 而不要再 linq 或拉姆达表示里写 这样的转换语。

        就是把变量 .ToString()  提到外面声明个变量  然后在拉姆达表达式里 直接使用这个变量

    2. 转换成 Enumerable

    IEnumerable是直接执行方法 ,而不调用Provider来转成其它的方式

     这样会把数据库里的查询出来 然后在内存里操作  所以数据库量大时 效率会低~

    八.ef4.1使用datatable

    datatable 在有的时候是非常有用的 例如 做报表等  因为我们不可能为每个报表建一个 实体类 这样比较麻烦

    这个时候返回datatable  则比较有用

    写一个扩展方法

    /// <summary>
           /// EF SQL 语句返回 dataTable
           /// </summary>
           /// <param name="db"></param>
           /// <param name="sql"></param>
           /// <param name="parameters"></param>
           /// <returns></returns>
           public static DataTable SqlQueryForDataTatable(this Database db,
                    string sql,
                    SqlParameter[] parameters)
           {
    
               SqlConnection conn = new System.Data.SqlClient.SqlConnection();
               conn.ConnectionString = db.Connection.ConnectionString;
               if (conn.State != ConnectionState.Open)
               {
                   conn.Open();
               }
               SqlCommand cmd = new SqlCommand();
               cmd.Connection = conn;
               cmd.CommandText = sql;
    
               if (parameters.Length>0)
               {
                   foreach (var item in parameters)
                   {
                       cmd.Parameters.Add(item);
                   }
               }
    
              
               SqlDataAdapter adapter = new SqlDataAdapter(cmd);
               DataTable table = new DataTable();
               adapter.Fill(table);
               return table;
           }

    调用如下:

    protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                GridView1.DataSource = GetDataTable();
                GridView1.DataBind();
            }
        }
    
    
        public DataTable GetDataTable()
        {
            GardenHotelContext context = new GardenHotelContext();
            int LanType = 0;
            int state = 0;
            SqlParameter[] sqlparams=new SqlParameter[2];
            sqlparams[0]=new SqlParameter("LanType",LanType);
            sqlparams[1]=new SqlParameter("state",state);
            DataTable DataTable = context.Database.SqlQueryForDataTatable("select LeaveName,LeaveEmail from LeaveInfo where LanType=@LanType and State=@State", sqlparams);
            return DataTable;
         
        }

    再分享一种方法  先上调用效果  利用返回的var 匿名类型  这样就无需声明实体类了

    public DataTable GetDataTable2()
        {
            GardenHotelContext context = new GardenHotelContext();
    
            var list = (from l in context.LeaveInfoes
                       group l by l.LanType into g
                       select new
                       {
                           g.Key,
                           num = g.Count()
                       }).ToList();
    
            return PubClass.ListToDataTable(list);
    
        }

    核心方法 反射调用 

    #region  反射List To DataTable
    
    
            /// <summary>  
            /// 将集合类转换成DataTable  
            /// </summary>  
            /// <param name="list">集合</param>  
            /// <returns></returns>  
            public static DataTable ListToDataTable(IList list)
            {
                DataTable result = new DataTable();
                if (list.Count > 0)
                {
                    PropertyInfo[] propertys = list[0].GetType().GetProperties();
                    foreach (PropertyInfo pi in propertys)
                    {
                        result.Columns.Add(pi.Name, pi.PropertyType);
                    }
    
                    for (int i = 0; i < list.Count; i++)
                    {
                        ArrayList tempList = new ArrayList();
                        foreach (PropertyInfo pi in propertys)
                        {
                            object obj = pi.GetValue(list[i], null);
                            tempList.Add(obj);
                        }
                        object[] array = tempList.ToArray();
                        result.LoadDataRow(array, true);
                    }
                }
                return result;
            }  
    
            #endregion
  • 相关阅读:
    ArcGlobe组件开发之动画4——加载保存动画
    ArcGlobe组件开发之3D符号化——接口篇
    ArcEngine 3D开发之3D符号化——接口篇
    ArcEngine 3D开发之IGlobeDisplayRendering2 接口
    ArcGlobe组件开发之IGlobeDisplayRendering2 接口
    oracle 11g各种下载地址
    redis memcached 和 mongoDb三者优缺点
    高并发 有哪些解决方案
    秒杀活动的高并发问题和超卖问题的解决方案
    php的运行原理,cgi和fast-cgi, php-cgi和php-fpm之间的联系区别
  • 原文地址:https://www.cnblogs.com/jordan2009/p/3468365.html
Copyright © 2020-2023  润新知