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 = ; 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") ==
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>)
{
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 = ;
int state = ;
SqlParameter[] sqlparams=new SqlParameter[];
sqlparams[]=new SqlParameter("LanType",LanType);
sqlparams[]=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 > )
{
PropertyInfo[] propertys = list[].GetType().GetProperties();
foreach (PropertyInfo pi in propertys)
{
result.Columns.Add(pi.Name, pi.PropertyType);
} for (int i = ; 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