【问题标题】:Return value mapping on Stored Procedures in Entity Framework实体框架中存储过程的返回值映射
【发布时间】:2010-12-23 17:16:32
【问题描述】:

我正在使用 EntityFramework 调用存储过程。但是我在部分实体类中设置的自定义属性为空。 我的 edmx 中有实体(我打电话给 edmx,我不知道该怎么称呼它)。例如,我的数据库中有一个“用户”表,所以我的实体上有一个“用户”类。 我有一个名为 GetUserById(@userId) 的存储过程,在这个存储过程中,我正在编写如下所示的基本 sql 语句

"SELECT * FROM Users WHERE Id=@userId"

在我的 edmx 中,我进行了函数导入以调用此存储过程并将其返回值设置为实体(也从下拉列表中选择用户)。当我像下面这样调用我的存储过程时,它可以完美运行

User user = Context.SP_GetUserById(123456);

但是我在存储过程中添加了一个自定义的新列,以返回一个如下所示的列

SELECT *, dbo.ConcatRoles(U.Id) AS RolesAsString
    FROM membership.[User] U
    WHERE Id = @id

现在,当我从 SSMS 执行它时,名为 RolesAsString 的新列出现在结果中。 为了在实体框架上工作,我向我的 User 类添加了一个名为 RolesAsString 的新属性,如下所示。

public partial class User
    {
        public string RolesAsString{ get; set; }
    }

但是当我调用它时,这个字段并没有被存储过程填充。 我查看我的 SP_GetUserById 的映射详细信息窗口,此窗口上没有映射。我想添加,但窗口是只读的,我无法映射它。我查看了 edmx 的来源,找不到任何关于 SP 映射的信息。

如何映射这个自定义字段?

【问题讨论】:

  • 首先——不要调用你的存储过程sp_(something)——这个命名是为微软保留的。其次 - 不要在你的存储过程中使用SELECT * FROM......
  • 感谢您的评论,为什么您说不要调用“select *”意味着写下所有列名,例如“select Id,Name,Email,....”?
  • 是的 - 当字段添加到数据库时,它可以保护您免受额外字段的影响,这可能会破坏您的 DAL,因为它不期望这些字段。切勿在任何地方使用SELECT *。现在,进入问题 - 您是否更新了模型浏览器中的函数导入?
  • 是的,我在模型浏览器上更新它,但没有任何反应。我还读到实体框架不查看部分类,因此它不会将“RolesAsString”列映射到实体属性。
  • 有人知道这个吗?我遇到了完全相同的情况,想知道是否有其他方法可以做到这一点。

标签: c# stored-procedures entity-framework-4 mapping


【解决方案1】:

您必须为 SP 创建一个复杂类型,而不是使用部分类。

【讨论】:

    【解决方案2】:

    尝试将属性添加到模型浏览器中的用户实体。如果在模型中定义它可能会起作用,而不是作为部分类......或者,最后,最简单的可能是让它返回一个实体,并将 SP 结果转换为用户结果,作为最后的手段。

    HTH。

    【讨论】:

      【解决方案3】:

      非常老的线程,但我今天遇到了这个确切的问题。

      一个区别是我没有将 SP 导入 dbContext 而是选择使用 SQLQuery 返回联系人实体列表。

      var allContacts = _dbContext.Database.SqlQuery<Contacts> 
      ("CRM.GetAllContactsForCustomer @customerID, param1).ToList();
      

      与 TS 一样,我创建了一个部分类来保存 SP 将返回的额外属性。

      public partial class Contacts
      {
          public EnumContactOrigin ContactOrigin { get; set; }
      }
      

      执行 SP 时不会填充此属性,与在 dbContext 中使用导入的 SP 时一样。

      出于某种原因,我想出了为联系人创建一个包装类来保存该额外属性的想法。

      public class ExtendedContacts : Contacts
      {
          public new EnumContactOrigin ContactOrigin { get; set; }
      }
      

      你猜怎么着,它有效! ContactOrigin 现在可以正确填写。

      var allContacts = _dbContext.Database.SqlQuery<ExtendedContacts> 
      ("CRM.GetAllContactsForCustomer @customerID, param1).ToList();
      

      在我的情况下,我可以将它作为一个包装类,因为我只使用联系人列表在网格中显示。

      我很想知道为什么这行得通?如果有另一种方法可以在不需要此 ExtendedContacts 类的情况下将额外属性检索到联系人中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-13
        • 1970-01-01
        • 2012-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多