类似的技术也是从网上学习的,以前也看到过更详细的技术文章,今日见有人发问,自己再杜撰一份,以充实下自己的技术博客。
这是代码片断,实现 Code First 调用存储过程,期待这个功能在将来新版本中有简化的方式。
第一步,有这样一个存储过程:
ALTER PROCEDURE [dbo].[sp_get_goods]
@all char(1),
@productID int
AS
select goods_id,gs_name,gs_id,goods_no,name,spec,gwt,nwt,voldesc,qtyunit ,price
--into t_product_temp
from t_goods g
第二步,定义好Class和Map,我通常用EF Power Tool生成
Product.CS
using System;
using System.Collections.Generic;
using System.Data.Services.Common;
namespace ERP.Domain
{
[DataServiceKey("ProductID")]
public class Product
{
public int ProductID { get; set; }
public string ProductNo { get; set; }
public string ProductName { get; set; }
public string ProductSpec { get; set; }
public decimal? GrossWeight { get; set; }
public decimal? NetWeight { get; set; }
public string VolumeDescribe { get; set; }
public string QuantityUnit { get; set; }
public decimal? Price { get; set; }
public string Currency { get; set; }
public string CategoryName { get; set; }
public int? CategoryID { get; set; }
}
}
ProductMap.CS
);
}
}
}
}
}
}
第三步:想办法执行context.Database.SqlQuery(mapCacheItem.MapType, sql, parameters)调用存储过程返回数据
SqlQueryService.CS
#endregion
}
}
}
}
第四步:这里的mapCacheItem.MapType是通过TypeBuilder依据ProductMap运行期创建的Type:
CreateDynamicType.CS
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);
}
}
}
第五步:从ProductMap的映射关系,可以构造出适合存储过程返回数据的类型,我还要借助AccessPrivateWrapper类访问ProductMap:
AccessPrivateWrapper.CS
true;
}
}
}
}
}
}
}
}
第六步:生成ProductList时,通过反射赋值,自己搞了个属性复制的功能类:
EntityReflectService.CS
null);
}
}
}
}
}
}
}
}
第七步:绕了一大圈,终于可以测试调用了,期待更轻量的调用存储过程的方式,性能还有待提升
return result;
}
}