如何将存储过程结果映射到自定义 class?
How to map a stored procedure result to a custom class?
我正在使用 entity framework 5
并且我已经在我的 .edmx
模型中添加了两个存储过程。
第一个存储过程return是一个字符串,如果我在Visual Studio中打开模型浏览器,我可以更改Returns a Collection Of
部分并将标量类型设置为String,如下:
然后在代码中,我可以调用SP并得到如下结果:
using (var context = new MyEntities())
{
var spResult = context.mySPNameFromTheModel(exampleParameter1, exampleParameter2); // This will get the output as string
}
上面的例子工作正常,但我怎样才能对 Complex 类型做同样的事情呢?
我的第二个存储过程return只有一行,两列,都是字符串。因此,我创建了一个具有两个字符串属性的 class,但是当我更改为 Complex 时我看不到它,我无法从下拉列表中 select 任何内容,因为它是空的。
当我点击 Get Column Information
时,它只是说 SP 没有 return 任何列,这是不正确的。
尝试为从 SP 返回的列添加别名。
例如:SELECT table1.id ID
- 检查edmx是否更新了相应的存储过程
- 尝试在模型浏览器中手动创建复杂类型。
- 保存并重建解决方案
- 然后尝试添加函数导入并在 Returns 集合 select 中为函数 importname、sp & 提供手动创建的复杂类型。
- 现在点击获取列信息。
- 然后点击确定。
我发现这篇 Mapping Stored Procedure Output to POCO Class 文章对回答 title 中指定的问题非常有帮助,因为我一直在寻找一种无需麻烦的方法使用 ADO.NET.
时写入字符串
public IList<Order> GetOrders(string CustomerID)
{
var orders = new List<Order>();
using (var con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
// Use count to get all available items before the connection closes
using (SqlCommand cmd = new SqlCommand("PagingProcTest", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@CustomerID", SqlDbType.NChar).Value = CustomerID;
cmd.Connection.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Map data to Order class using this way
orders = DataReaderMapToList<Order>(reader).ToList();
// instead of this traditional way
// while (reader.Read())
// {
// var o = new Order();
// o.OrderID = Convert.ToInt32(reader["OrderID"]);
// o.CustomerID = reader["CustomerID"].ToString();
// orders.Add(o);
// }
}
cmd.Connection.Close();
}
}
return orders;
}
private static List<T> DataReaderMapToList<T>(DbDataReader dr)
{
List<T> list = new List<T>();
while (dr.Read())
{
var obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
if (!Equals(dr[prop.Name], DBNull.Value))
{
prop.SetValue(obj, dr[prop.Name], null);
}
}
list.Add(obj);
}
return list;
}
我正在使用 entity framework 5
并且我已经在我的 .edmx
模型中添加了两个存储过程。
第一个存储过程return是一个字符串,如果我在Visual Studio中打开模型浏览器,我可以更改Returns a Collection Of
部分并将标量类型设置为String,如下:
然后在代码中,我可以调用SP并得到如下结果:
using (var context = new MyEntities())
{
var spResult = context.mySPNameFromTheModel(exampleParameter1, exampleParameter2); // This will get the output as string
}
上面的例子工作正常,但我怎样才能对 Complex 类型做同样的事情呢?
我的第二个存储过程return只有一行,两列,都是字符串。因此,我创建了一个具有两个字符串属性的 class,但是当我更改为 Complex 时我看不到它,我无法从下拉列表中 select 任何内容,因为它是空的。
当我点击 Get Column Information
时,它只是说 SP 没有 return 任何列,这是不正确的。
尝试为从 SP 返回的列添加别名。
例如:SELECT table1.id ID
- 检查edmx是否更新了相应的存储过程
- 尝试在模型浏览器中手动创建复杂类型。
- 保存并重建解决方案
- 然后尝试添加函数导入并在 Returns 集合 select 中为函数 importname、sp & 提供手动创建的复杂类型。
- 现在点击获取列信息。
- 然后点击确定。
我发现这篇 Mapping Stored Procedure Output to POCO Class 文章对回答 title 中指定的问题非常有帮助,因为我一直在寻找一种无需麻烦的方法使用 ADO.NET.
时写入字符串public IList<Order> GetOrders(string CustomerID)
{
var orders = new List<Order>();
using (var con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
// Use count to get all available items before the connection closes
using (SqlCommand cmd = new SqlCommand("PagingProcTest", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@CustomerID", SqlDbType.NChar).Value = CustomerID;
cmd.Connection.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Map data to Order class using this way
orders = DataReaderMapToList<Order>(reader).ToList();
// instead of this traditional way
// while (reader.Read())
// {
// var o = new Order();
// o.OrderID = Convert.ToInt32(reader["OrderID"]);
// o.CustomerID = reader["CustomerID"].ToString();
// orders.Add(o);
// }
}
cmd.Connection.Close();
}
}
return orders;
}
private static List<T> DataReaderMapToList<T>(DbDataReader dr)
{
List<T> list = new List<T>();
while (dr.Read())
{
var obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
if (!Equals(dr[prop.Name], DBNull.Value))
{
prop.SetValue(obj, dr[prop.Name], null);
}
}
list.Add(obj);
}
return list;
}