Entity Framework Code First Approach with User Defined Functions

在当今的软件开发中,Entity Framework 是一个广泛使用的 ORM(对象关系映射)框架。其中,代码优先(Code First)的方法因其提高代码模块化和易于维护的特性而广受欢迎。与数据库优先(Database First)的方法相比,Entity Framework 目前并没有直接提供与用户定义函数直接通信的简单方式。

在处理一个项目时,遇到了一个需求,需要直接使用 Entity Framework 与用户定义的函数进行通信。虽然可以通过以下代码实现: db.Database.SqlQuery<MyModel>("select * from usr_func()"); 但希望代码更加清晰和结构化,以便更好地处理这个函数。因此,决定编写一个库,实现自定义逻辑,使这个功能更加模块化和结构化。在查阅了不同的博客后,发现了 aureolin 写的《Code First Stored Procedures》博客。下载了它的最新版本,并对其进行了重大修改,最终成功了。

首先,来看一个使用 SQL Server 创建的简单表值函数: CREATE FUNCTION ufn_MyFunction(@id int) RETURNS TABLE AS RETURN (SELECT * from tbl_Customer where Id = @id); 这个函数接受 @id 作为参数,并根据 id 返回表记录。这只是一个示例,实际实现可以接收任何类型或没有参数,并返回包含大量逻辑的查询。

现在,让看看如何使用代码优先方法映射这个函数。首先,创建一个类来传递这个函数的参数。使用以下代码创建它: public class TestFunctionParams { [CodeFunctionAttributes.FunctionOrder(1)] [CodeFunctionAttributes.Name("id")] [CodeFunctionAttributes.ParameterType(System.Data.SqlDbType.Int)] public int Id { get; set; } } 在这里,提到了函数顺序,因为按顺序传递函数参数非常重要。如果有多个参数,那么需要添加它们的顺序以传递给函数。此外,还编写了许多其他属性来处理不同的操作,如参数的名称和类型。

现在,将在数据上下文类中初始化库,并添加以下代码到 DbContext 类的构造函数中: public DataContext() : base("name=SqlConn") { this.InitializeTableFunctions(); }

接下来,将函数添加为数据上下文类中的属性,如下所示: [CodeFunctionAttributes.Schema("dbo")] [CodeFunctionAttributes.Name("ufn_MyFunction")] [CodeFunctionAttributes.ReturnTypes(typeof(Customer))] public TableValueFunction<TestFunctionParams> CustomerFunction { get; set; } 现在整个数据库上下文将如下所示: public class DataContext : DbContext { public DataContext() : base("name=SqlConn") { System.Data.Entity.Database.SetInitializer<DataContext>(null); this.InitializeTableFunctions(); } public DbSet<Customer> Customers { get; set; } [CodeFunctionAttributes.Schema("dbo")] [CodeFunctionAttributes.Name("ufn_MyFunction")] [CodeFunctionAttributes.ReturnTypes(typeof(Customer))] public TableValueFunction<TestFunctionParams> CustomerFunction { get; set; } }

最后,一切都设置好了。现在可以很容易地使用以下代码调用这个函数: static void Main(string[] args) { using (var db = new DataContext()) { var funcParams = new TestFunctionParams() { Id = 1 }; var entity = db.CustomerFunction.ExecuteFunction(funcParams).ToList<Customer>(); } } 函数的最终结果将返回到对象中,并转换为列表并映射到模型。通过这种方式,可以添加可以接收任何数量和任何类型的参数的函数(还可以使用方法参数使用 SqlDbType.Structured)并将其映射到模型。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485