EF 6 数据库优先:如何更新存储过程?

Posted

技术标签:

【中文标题】EF 6 数据库优先:如何更新存储过程?【英文标题】:EF 6 database first: How to update stored procedures? 【发布时间】:2013-12-29 09:17:10 【问题描述】:

我们使用Entity Framework 6.0.0 并首先使用数据库(like this) 从表和存储过程生成代码。这似乎很好用,只是在更新或刷新模型时不会反映存储过程中的更改。向表中添加列会被反映,但不会向存储过程中添加字段。

有趣的是,如果我转到Model Browser,右键单击存储过程,选择Add Function Import,然后单击按钮Get Column Information,我们可以看到正确的列。这意味着模型知道列,但无法更新生成的代码。

有一种解决方法,即在更新模型之前删除生成的存储过程。只要您没有对存储过程进行任何编辑,这就会起作用。有谁知道避免这种解决方法的方法?

我正在使用 Visual Studio 2013 以及截至 2013 年 12 月初的所有最新更新。

提前致谢!

更新 1: andersr 的回答在一种情况下有所帮助,其中存储过程使用了一个临时表,所以我给了他 +1,但它仍然没有解决更新简单存储过程的主要问题。

更新 2: shimron 在下面的评论链接到关于 EF 3.5 中相同问题的问题。 EF 6.0 似乎仍然如此。阅读它以了解另一种方法,但我现在的结论是,最简单的方法是在更新模型之前删除生成的存储过程。如果您想做一些花哨的事情,请使用部分类。

【问题讨论】:

这个问题“刷新实体框架 3.5 中的存储过程”与您的问题类似。这里:***.com/questions/4995226/… 【参考方案1】:

基于DaveD 的this answer,这些步骤解决了这个问题:

    在您的 .edmx 中,按住 rt 键并选择 模型浏览器。 在模型浏览器中(在 VS 2015 默认配置中,它是解决方案资源管理器中的一个选项卡),展开模型下的 Function Imports。 双击您的存储过程。 点击Returns a Collection Of - Complex旁边的更新按钮(如果不返回标量或实体) 点击okay,然后save您的 .edmx 以反映整个项目中存储过程的字段更改。

【讨论】:

这会更新为返回值生成的复杂类型。知道更新数据库后如何更新模型中存储过程的参数吗? 要回答我自己的问题,使用“从数据库更新模型...”向导刷新整个模型。 如果您没有 .edmx 文件怎么办? 这种方法仅供参考,虽然在 Visual Studio 2017 的所有版本中都有效,但此方法在 Visual Studio 2019 版本 16.0.0 中不起作用【参考方案2】:

您的存储过程是否会从临时表中返回数据? EF 似乎不支持这一点,请参阅EF4 - The selected stored procedure returns no columns 了解更多信息。

但是,如您所见,存储过程将在模型浏览器中可用。我对上述场景进行了快速测试。 存储过程是在我的上下文类中生成的,但返回类型是 int 而不是复杂类型。有关可能的解决方法,请参阅上面的链接。

【讨论】:

+1 因为这有助于使用临时表的存储过程,但它并没有真正解决主要问题(请参阅上面的更新)。还是谢谢!【参考方案3】:

我刚刚遇到这个问题,我的解决方法(真的很讨厌)是在存储过程的顶部创建一个条件永远不会为真的 if 语句,该存储过程选择与带有显式转换的查询相同的输出列表到我要返回的数据类型。这将假定您的类型可以为空,因此要解决您将转换包装在 ISNULL

中的问题

例如,如果您的输出包含以下列:

UserId (int, not null)
RoleId (int, nullable)
FirstName (varchar(255), nullable)
Created (datetime, not null)

你会期望这样创建一个 POCO:

SomeClass 
    public int UserId  get; set; 
    public int? RoleId  get; set; 
    public string FirstName  get; set; 
    public DateTime Created  get; set; 

...但事实并非如此,这就是我们今天在这里的原因。为了解决这个无法按预期工作的问题,我将以下内容放在我的 SP 的顶部(就在“AS”之后):

if(1=0)
begin
    select
        UserId = isnull((cast(0 as int)),0),
        RoleId = cast(0 as int),
        FirstName = cast(0 as varchar),
        DateTime = isnull((cast(0 as datetime)),'')
end

它既可怕又丑陋,但每次都对我有用。希望我们能尽快获得解决此问题的工具更新...今天发生在我身上,SQL Server 2016 w/VS2015 中没有临时表...

希望这对某人有所帮助

【讨论】:

删除后重新添加SP不是更好吗? 是的,世界变得更好了——但不幸的是,删除并重新添加 SP 给了我同样奇怪的结果 我想如果你打开模型浏览器,删除SP,复杂类型和函数导入,关闭并重新打开解决方案并添加SP,它必须工作! 是的,您需要删除所有 3 个工件:sp、复杂类型和函数导入才能正常工作

以上是关于EF 6 数据库优先:如何更新存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

在.net 中使用EF 连接oracle 数据库,如何使用存储过程。求高手指点,help!

如何使用 EntityFramework 调用存储过程?

EF工作流程

EF 存储过程(下)

EF执行SQL语句和存储过程

如何在不知道查询结果类型的情况下在 EF/VB.net 中运行存储过程?