我已将我的项目从Linq-to-SQL迁移到Entity Framework 6.解决了这么多问题之后,我终于找到了一个我不知道如何处理它。转换后,大约三分之一的单元测试失败,因为存储过程返回标量值just work different way。
在Linq-to-SQL中,存储过程返回返回的值。在EF中,它们返回受影响的行数。有一些变通方法需要更改存储过程(通常从RETURN @retvalue
到SELECT @retvalue
)。但这需要改变T-SQL。该项目仍然包含一些旧时代的遗留代码,如aspnet_Membership_CreateUser
等。这意味着我无法更改这些存储过程,因为ASP.NET ADO.NET成员资格提供程序部分使用,部分由Linq-to-SQL代码使用。我考虑的解决方案是使这些部分遗留代码的T-SQL包装。
我希望保持存储过程不变的另一个原因是,如果升级到EF不成功,则可能会恢复到先前的提交。 A不想再次更改数据库。但这个理由不是那么强烈,只是关于我的懒惰。
我知道会员提供者是老式的,但我无法在一次提交中重写整个应用程序,我需要保持稳定。
完成迁移的最佳方法是从Lin调用存储过程,如Linq-to-SQL,但我没有找到方法。 EF让我很失望。经过多年的开发,EF怎么可能不支持从存储过程中返回标量值?
你会如何解决这个问题?
答案 0 :(得分:0)
你好Qub1n,
// Create the gender parameter var param1 = new SqlParameter {
ParameterName = "@userId",
Value = _userId };
// Create the return code var returnValue = new SqlParameter {
ParameterName = "@ReturnCode",
SqlDbType = System.Data.SqlDbType.Int,
Direction = System.Data.ParameterDirection.Output };
// Gender is an int column in the database.
_context
.Database
.ExecuteSqlCommand("exec @ReturnCode = GetGenderOfUser @userId",
param1, returnValue);
return (int)returnValue.Value;
这对我有用。我的存储过程是这样的:
CREATE PROCEDURE [dbo].[GetGenderOfUser]
-- Add the parameters for the stored procedure here
@userId uniqueidentifier
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @retval int
-- Insert statements for procedure here
set @retval = (select top(1) Gender from Users where Guid = @userId)
return @retval
END
让我知道这是否有效!
答案 1 :(得分:0)
Finnaly我最终得到了包装器,它保留了数据库的原始功能(用于ASP.NET MembershipProvider)并为EntityFramework创建了存储过程的版本:
CREATE PROCEDURE [dbo].[aspnet_UsersInRoles_AddUsersToRolesEF]
@ApplicationName nvarchar(256),
@UserNames nvarchar(4000),
@RoleNames nvarchar(4000),
@CurrentTimeUtc datetime
AS
BEGIN
DECLARE @return_value int
EXEC @return_value = [dbo].[aspnet_UsersInRoles_AddUsersToRoles]
@ApplicationName,
@UserNames,
@RoleNames,
@CurrentTimeUtc
SELECT @return_value
END
GO
现在我可以使用编译器检查存储过程中参数的数量和类型。