[转] Entity Framework Stored Procedure Generation

At work my team and I are utilizing the ADO.NET Entity Framework as a means to mitigate the object-relational impedance mismatch. Simply put, we’re utilizing it as an object-relational mapper for our latest project. So far we have been really impressed with the flexibility it provides us, especially surrounding the area of mapping the same table to multiple entity types and creating inheritance relationships among those entity types. It has proven itself as a much more viable candidate than .netTiers or LINQ to SQL for us.

While I have a lot of praise for the Entity Framework, there are some quirks that take getting used to. For example, you can’t update properties that are part of a primary key, even though you can update (non-identity) columns that are part of the primary key in SQL Server 2005. Another is the requirement that if an entity will be inserted into the database using a stored procedure, it must also be updated and deleted through a stored procedure. Yet another is that each stored procedure mapped to a particular entity type must have parameters mapped to every association key, regardless of the type of stored procedure (INSERT, UPDATE, or DELETE). For example, consider the following model:

image 

If I created stored procedures for the Account entity to use in my EF model, they’d look like this:

CREATE PROC dbo.Account_Insert

(

    @customerId INT

)

AS

BEGIN

    INSERT INTO Account (customerId)

    VALUES (@customerId)

 

    SELECT SCOPE_IDENTITY() as accountId

END

GO

 

CREATE PROC dbo.Account_Update

(

    @accountId INT,

    @customerId INT

)

AS

BEGIN

    UPDATE Account

    SET customerId = @customerId

    WHERE accountId = @accountId

END

 

CREATE PROC dbo.Account_Delete

(

    @accountId INT,

    @customerId INT

)

AS

BEGIN

    DELETE FROM Account

    WHERE accountId = @accountId

END

Notice the delete stored procedure—it must take in both the ID of the Account and the ID of the Customer it is associated with. Based on Colin Meek’s post here, I can understand why this is necessitated by the Entity Framework, but I can’t dispute the fact that it is different from I’m used to writing stored procedures.

As we moved towards implementing sprocs for our persistence layer to utilize, we ran into a few problems. At first, we thought we could utilize old templates from CodeSmith and .netTiers to generate sprocs, and our EF model would consume them gracefully. Unfortunately, if we used these templates, we would end up with sprocs like this for the Account table:

CREATE PROC dbo.Account_Insert

(

    @accountId INT OUTPUT,

    @customerId INT

)

AS

BEGIN

    INSERT INTO Account (customerId)

    VALUES (@customerId)

 

    SET @accountId = SCOPE_IDENTITY()

END

GO

 

CREATE PROC dbo.Account_Update

(

    @accountId INT,

    @customerId INT

)

AS

BEGIN

    UPDATE Account

    SET customerId = @customerId

    WHERE accountId = @accountId

END

 

CREATE PROC dbo.Account_Delete

(

    @accountId INT

)

AS

BEGIN

    DELETE FROM Account

    WHERE accountId = @accountId

END

Notice the slight differences:

  1. The INSERT sproc takes in an output parameter for the identity column and then sets the value of that parameter to the ID that was just inserted. The EF version of the sproc does not take in an output parameter; instead it just selects SCOPE_IDENTITY() for the EF to merge back into the Account entity that was inserted.
  2. The DELETE sproc does not take the parameter for the Customer ID, because it is not part of the primary key.

This causes some vexation for us because our new business domain houses about forty tables for which we need to write CUD sprocs that fit the Entity Framework’s rules. We could write them by hand (which would be painful and subject to error), try to modify CodeSmith’s templates to generate them correctly, or try to generate them using some other way.

From the title of this blog entry, you can probably infer that we didn’t write them by hand. Furthermore, Ryan Hauert and I were toying around with the idea of using T4 Templates to generate the SQL we needed. In all honesty, we didn’t even consider modifying the CodeSmith templates; I don’t think this was a bad choice, as T4 templates can benefit people who don’t want to purchase CodeSmith, but it may’ve been easier for our particular situation. But I digress…

The T4 template we created is designed to be a general purpose way to generate CUD procedures for an Entity Framework model. In case you didn’t read the links I provided on the templates, they are code-generation files which are intrinsically recognized by Visual Studio 2008. (They required the VS SDK in VS2005.) They have a .tt extension, and Visual Studio will nested generated code files underneath them in the Solution Explorer, similar to how designer files are nested under Entity Framework and LINQ to SQL models.

image

It’s a very simple process to use the T4 template:

  1. Add the file into your project. (The file is linked at the end of the blog entry.)
  2. Simply save the template file and CUD sprocs will be generated for every EDMX file in the current directory.

If you want to change what directory the template looks in or what files it generates sprocs for, look at the configuration parameters on lines 24 and 25 in the picture above. You can specify the directory explicitly by initializing the directoryName variable to anything other than the empty string or null. Furthermore, if you want to match a specific EDMX file only, you can use a regular expression to filter out unwanted files. I could use it like this:

Regex edmxFileFilter = new Regex(@"Entities\.edmx");

Then only the Entities.edmx file would be processed.

The template not only generates EF-compliant sprocs, but it also considers only the tables that are in the SSDL of the model file. Unfortunately, the template must query the database (SQL Server 2005 only!) in order to make all the decisions necessary to create the output file. However, this is usually quite fast on generations other than the first one.

As you can see from the picture above, the template requires a few different assemblies to be installed. Most of them shouldn’t be a problem when generating EF sprocs, because it strongly suggests that you have the .NET Framework 3.5 installed. Something you may not have are the SQL Server Server Management Objects (SMO), which offer an abstraction layer over the metadata of a SQL Server instance (e.g. databases, tables, columns, keys, indexes, data types), and keep the template cleaner than if we had to make ad hoc queries directly. The SMO installation is available on this page, where its installer is called "SQLServer2005_XMO.msi." There are other installers for 64-bit and Itanium 64-bit.

Once that is installed the template is very simple to run and gives us output like this:

image

Now we can take this script and run it against SQL Server and then import the sprocs into our Entity Framework model. Finally we can map the stored procedures to the entity types they encapsulate and voilà! We’re done.

There are a few limitations with the template the moment, but it will account for most cases:

  1. No stored procedures are generated for tables that do not have primary keys (in the database, not in the EF model). There is no way we can infer what you meant for the key to be for the update and delete sprocs; while we could generate insert procedures, it wouldn’t help the end user because the EF requires that an entity type be mapped to all three, or none at all.
  2. The template is available only in C# at the moment.
  3. It has not been tested in all scenarios, so any feedback you have would be great. :)
  4. It does not account for entity inheritance.

Download T4 Template

Special thanks to Bob Pace for giving Ryan and me the idea and providing helpful resources on T4.

Also, if you want to get started writing your own T4 templates, check out Hilton Giesenow’s excellent video here.

May 22, 2008 – Updates:

Ryan and I ran into an issue recently where we were accidentally comparing all of the parameters against values in database rows for the delete stored procedures. This was a mistake, because we really only need to check for equality on the primary key columns. The new template has been uploaded.

转载于:https://www.cnblogs.com/JosephLiu/archive/2010/02/17/1668850.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Entity Framework是微软开发的一种对象关系映射(ORM)框架,用于在.NET应用程序中与数据库进行交互。它提供了一种简化和自动化数据库操作的方式,使开发人员能够使用面向对象的方式来处理数据库。 在上述引用中,是一个示例代码,展示了如何创建一个继承自DbContext的自定义数据库上下文类MyDBContext,并定义了一个DbSet属性Persons,用于表示数据库中的Person表。此外,还重写了OnModelCreating方法,用于配置数据库模型。 是关于Entity Framework的一些开发团队的建议。他们强烈建议使用using语句来确保DbContext实例的正确释放,以避免潜在的资源泄漏问题。同时,他们指出,仅仅为了利用延迟加载而不使用using语句是违反分层原则的。 以下是一个简单的示例,演示了如何使用Entity Framework进行数据库操作: ```csharp using (var context = new MyDBContext()) { // 查询所有的Person记录 var persons = context.Persons.ToList(); // 添加新的Person记录 var newPerson = new Person { Name = "John", Age = 25 }; context.Persons.Add(newPerson); context.SaveChanges(); // 更新Person记录 var personToUpdate = context.Persons.FirstOrDefault(p => p.Name == "John"); if (personToUpdate != null) { personToUpdate.Age = 30; context.SaveChanges(); } // 删除Person记录 var personToDelete = context.Persons.FirstOrDefault(p => p.Name == "John"); if (personToDelete != null) { context.Persons.Remove(personToDelete); context.SaveChanges(); } } ``` 这个示例展示了如何使用Entity Framework的DbContext类来查询、添加、更新和删除数据库中的Person记录。使用using语句确保DbContext实例在使用完毕后被正确释放。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值