我将 EF 5 与 .NET 4.5 一起使用,我为我的数据库创建了一个模型并将我的函数导入到模型中,我可以成功导入 TVF 和 SP,但我无法导入具有标量返回值的函数。设计师有可能还是我应该手动编辑edmx
文件?
3 回答
向下滚动到此页面上的标量值函数部分:
使用 Entity Framework 5 进行数据库优先开发 - 导入标量值函数
您可以遵循这个丑陋的解决方法,也可以遵循我将在此答案底部给出的建议。
这是该文章的摘录(关于解决方法):
“此方法需要直接对 .edmx 文件的 xml 进行一些小的更改。为此,请右键单击 .edmx 文件并选择“打开方式...”、“XML(文本)编辑器”。这就是函数的外观在更改之前的 .edmx 文件中:
<Function Name="CountActivities" ReturnType="int" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="personId" Type="int" Mode="In" />
</Function>
<Function Name="CountHydrations" ReturnType="int" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="personId" Type="int" Mode="In" />
</Function>
<Function Name="CountMeals" ReturnType="int" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="personId" Type="int" Mode="In" />
</Function>
“从元素中删除 'ReturnType' 属性。然后,为每个元素添加一个元素。有关元素的内容,请参阅下面修改后的 .edmx 文件。
<Function Name="CountActivities" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<CommandText>
SELECT [dbo].[CountActivities] (@personId)
</CommandText>
<Parameter Name="personId" Type="int" Mode="In" />
</Function>
<Function Name="CountHydrations" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<CommandText>
SELECT [dbo].[CountHydrations] (@personId)
</CommandText>
<Parameter Name="personId" Type="int" Mode="In" />
</Function>
<Function Name="CountMeals" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<CommandText>
SELECT [dbo].[CountMeals] (@personId)
</CommandText>
<Parameter Name="personId" Type="int" Mode="In" />
</Function>
“接下来,在模型浏览器中,右键单击 'Function Imports' 文件夹并选择 'Add Function Import...' 这将打开 'Add Function Import' 对话框窗口。我们将 'CountActivities' 标量值函数导入到显示此方法。在对话窗口中输入以下信息,然后选择保存。”
我的建议: 考虑到所需的工作量,创建一个只返回一行以达到相同效果和目的的表值函数要容易得多。
下面是 SQL Server 中用户定义的表值函数的示例:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[udfGetTotalMinutesInvoiced] ( @billingType INT )
RETURNS TABLE
AS
RETURN
(
SELECT
SUM([ProgressNote].[TotalMinutes]) AS 'TotalMinutesInvoiced'
FROM
[dbo].[InvoiceEntry]
JOIN [dbo].[ProgressNote]
ON [ProgressNote].[ProgressNoteID] = [InvoiceEntry].[ProgressNoteID]
WHERE
[InvoiceEntry].[BillingTypeID] = @billingType
AND progressNote.[IsRecordedInInvoiceEntry] = 1
)
GO
另请注意,您实际上可以从表值函数中调用标量值用户定义函数。
要调用表值函数,您可能希望使用 FirstOrDefault 方法,如下所示:
private void UpdateStatisticsPanel()
{
var billingTypeId = int.Parse(txtBillingTypeId.Text);
var totalMinutesInvoiced = context.udfGetTotalMinutesInvoiced(billingType: billingTypeId);
var minutesInvoiced = totalMinutesInvoiced.FirstOrDefault();
var invoiced = new Tuple<string, int?>("totalMinutesInvoiced:", minutesInvoiced);
lstFinancialSummary.Items.Add(invoiced);
var totalMinutesNotInvoiced = context.udfGetTotalMinutesNotInvoiced(billingType: billingTypeId);
var minutesNotInvoiced = totalMinutesNotInvoiced.FirstOrDefault();
var notInvoiced = new Tuple<string, int?>("totalMinutesNotInvoiced:", minutesNotInvoiced);
lstFinancialSummary.Items.Add(notInvoiced);
// remember to push the values up to the ListView.
}
在同一个问题上苦苦挣扎了将近一天,恕我直言@devinbost,它并没有解决问题,但它让我更接近解决方案。总之,唯一的解决方案是将函数标量类型转换为表中具有单个值的表值类型,请参阅代码示例。
您不必更改 EDMX XML 中的任何内容,请修改 SQL 函数
原来的标量函数,它不起作用
CREATE FUNCTION [dbo].[GetSha256]
(
-- Add the parameters for the function here
@str nvarchar(max)
)
RETURNS VARBINARY(32)
AS
BEGIN
RETURN ( SELECT * FROM HASHBYTES('SHA2_256', @str) AS HASH256 );
END -- this doesn't work.
标量函数 -> 转换为表值函数,它可以工作
CREATE FUNCTION [dbo].[GetSha2561]
(
-- Add the parameters for the function here
@str nvarchar(max)
)
RETURNS @returnList TABLE (CODE varbinary(32))
AS
BEGIN
INSERT INTO @returnList
SELECT HASHBYTES('SHA2_256', @str);
RETURN; -- This one works like a charm.
END
Edmx 截图
我无法从存储过程中检索返回参数,因此在调用存储过程时我使用了 context.Database.ExecuteSqlCommand 而不是“SqlQuery”,它可以工作。希望这个建议可以帮助某人。