问题详细描述如下:我在SQL server中创建了带一个input,表值参数的存储过程,然后用Enterprise Library5.0调用这个存储过程,并将.net中DataTable类型的变量传进去。具体代码如下:
1.SQL:
1 CREATE PROCEDURE [dbo].[CreatFoodTestTableType]
2 @foodTable FoodTableType readonly --表值参数类型FoodTableType已创建
3 AS
4 BEGIN
5 insert into PFood(CID,PageIndex) select CID,PageIndex from @foodTable
6 END
2.C#:
public int Test()
{
//字符串从配置文件中读取
Database db1 = DatabaseFactory.CreateDatabase("ConnectionString");
DataTable dt = new DataTable();
DataColumn dc1 = new DataColumn("Id", typeof(int));
DataColumn dc2 = new DataColumn("PageIndex", typeof(int));
dt.Columns.AddRange(new DataColumn[] { dc1, dc2, dc3 });
for (int i = 0; i < 10; i++)
{
DataRow dr = dt.NewRow();
dr[0] = 10 + i;
dr[1] = 20 + i;
dt.Rows.Add(dr);
}
DbCommand cmd = db1.GetStoredProcCommand("CreatFoodTestTableType");
//这里的DbType不知道选什么
db1.AddInParameter(cmd, "@foodTable", DbType.Object, dt);
return db.ExecuteNonQuery(cmd);
}
存储过程我直接用ado.net测试可以成功(ado.net的SqlDataType中有个叫Udt类型),但enterprise Library5.0中没有那个类型,现在的问题就是如何使用Enterprise library调用带表值参数的存储过程,请各位大侠帮帮忙,小弟不胜感激
public static SqlCommand BatchSaveHotelSalesInfo(BatchSaveHotelSalesInfoParamEntity entity){ if(null == entity) throw new ArgumentNullException("entity"); object value; SqlCommand sc = new SqlCommand("usp_BatchSaveHotelSalesInfo"); sc.CommandType = CommandType.StoredProcedure; //表类型参数不能为 DBNull, null 会自动转换成 Sql 语句里的 default value = entity.HotelSaleInfos.ToDataTable<THotelSalesInfoEntity>(); SqlParameter spHotelSaleInfos = new SqlParameter("@HotelSaleInfos", SqlDbType.Structured, -1 , ParameterDirection.Input , true, 0 , 0 , string.Empty, DataRowVersion.Default, value); sc.Parameters.Add(spHotelSaleInfos); SqlParameter sp = new SqlParameter("@ReturnValue", SqlDbType.Int); sp.Direction = ParameterDirection.ReturnValue; sc.Parameters.Add(sp); return sc; }
/// <summary> /// 将 List 转换为 DataTable, 只针对 T 中 的 public Property /// </summary> /// <typeparam name="T"></typeparam> /// <param name="list"></param> public static DataTable ToDataTable<T>(this List<T> list) where T : class { if (list == null) return null; Type type = typeof(T); var ps = type.GetProperties(); Type targetType; NullableConverter nullableConvert; List<DataColumn> cols = new List<DataColumn>(); foreach(var p in ps){ if(p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))){ nullableConvert = new NullableConverter(p.PropertyType); targetType = nullableConvert.UnderlyingType; cols.Add(new DataColumn(p.Name, targetType)); }else{ cols.Add(new DataColumn(p.Name, p.PropertyType)); } } //var cols = from p in ps // let pp = p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>) // select new DataColumn(p.Name, p.PropertyType); DataTable dt = new DataTable(); dt.Columns.AddRange(cols.ToArray()); list.ForEach((l) => { List<object> objs = new List<object>(); objs.AddRange(ps.Select(p => p.GetValue(l, null))); dt.Rows.Add(objs.ToArray()); }); return dt; }
晕,这样也可以吗? 能不能贴上你的 ado.net的代码,让我学习一下
存储过程中定义的是什么就用什么。
如果用SqlCommand,可以不指定DbType,比如:
command.Parameters.AddWithValue("@Title",doc.Title);
你说的方法我试过,就是把Database和DbCommand分别as为SqlDatabase和SqlCommand
但执行ExecuteNonQuery方法返回值为-1而不是10,虽然数据确实已经被insert进数据库了
@DT2: 不要as, 直接用SqlDatabase和SqlCommand
@DT2: 能不能贴上你的 ado.net的代码,让我学习一下?
@dudu:
DatabaseFactory.CreateDatabase("ConnectionString");这个方法创建的Database就是一个通用的DB,如果不as怎么得到SqlDatabase?还有就是,如果直接用ado.net的访问方式就跟Enterprise library没关系了啊
@ChatinCode:
1 ado.net的访问方式如下:
2
3 string dbCon = "Data Source=.;Initial Catalog=Food;Integrated Security=True";
4 using (SqlConnection conn = new SqlConnection(dbCon))
5 {
6 SqlCommand cmd = new SqlCommand("CreatFoodTestTableType", conn);
7 cmd.CommandType = CommandType.StoredProcedure;
8 cmd.Parameters.AddWithValue("@foodTable", dt);
9 conn.Open();
10 int i = cmd.ExecuteNonQuery();
11 return i;
12 }
13
14 仅供参考,如有不对的地方,请指正,谢谢!
@DT2: 谢谢,FoodTableType 的定义呢? 代码方便贴出来吗?