【问题标题】:Error no mapping column in Entity 6 DB first designEntity 6 DB first design 中的错误没有映射列
【发布时间】:2017-03-21 21:34:20
【问题描述】:

我有一个无法重写的旧版 mvc 应用程序。有一个存储过程,它返回表A 的所有列名,ID 除外。 (注意,它实际上并没有从表 A 中选择,而是恰好返回了相同的列名)。我希望调用存储过程(通过 SQL 查询),并将结果分配给 A 类的变量。但是,我得到一个 System.Data.Entity.Core.CommandExecutionException“ID”类型的成员没有相应的列在同名的数据阅读器中

我的代码如下:

A类

namespace LegacyApp.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations.Schema;

    public partial class A
    {
        [NotMapped]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }
        public Nullable<int> SOId { get; set; }
        public string SODesc { get; set; }
        //... 
    }
}

我的控制器

public class MyController : Controller
{
    private MyDBContext db = new MyDBContext();
    //...

    [HttpPost]
    [ValidateInput(false)]
    [OutputCache(NoStore = true, Duration = 0)]
    public ActionResult Index(ViewModel rb)
    {
        var query = this.buildQuery().ToString();

        // The results returned by the query contain all members of A except for ID
        IEnumerable<A> goals = db.Database.SqlQuery<A>(query);

        // Exception occurs here
        List<A> goalList = goals.ToList();
        rb.goalList;
        return View(rb);
    }
}

.edmx 设计器中的 ID 属性

我假设[NotMapped][DatabaseGenerated(DatabaseGeneratedOption.Identity)] 注释应该忽略ID?我这样做的原因是因为用户将过滤查询的数据集,然后将过滤后的结果插入到表 A 中。由于表 A 使用具有自动递增的 PK ID,我希望 ID插入时为NULL。我已经从实体设计器更新了我的模型,但我仍然收到错误消息。这样做的正确方法是什么?

【问题讨论】:

  • 看看DatabaseGeneratedOption.Identity
  • 我的意思是返回 ID,但是使用 Identity 属性来表明这是 DB 应该触及的东西。
  • 1)您需要从 sql 中返回 ID 2)您不需要 [NotMapped] 属性 3)您确实需要 Identity 属性。有了所有这些,db 将返回带有 ID 的整个实体(并且实体框架需要每个对象的密钥),数据库将使用自动增量更新 ID,然后 EF 将获取该 ID。
  • 不幸的是,sp 没有返回 ID(我无法修改它)。话虽如此,还有其他方法吗?

标签: c# sql-server entity-framework


【解决方案1】:

当您从数据库中读取实体时,您可以使用 projection - 一个只包含您选择的字段的类。

当您插入/更新实体时,该实体应映射到模型中,始终具有键等。

从技术上讲,投影可以是任何类,并且不需要包含在模型中。

我看到您的情况有以下选择:

  1. 创建绝对独立的Dto 类,并使用您拥有的存储过程将其用于SELECTing
  2. 如果存储过程选择原始字段的子集并且不引入新字段 - 您可以像 Entity : Dto 那样组织类层次结构,并使用 Dto 表示 SELECTing,使用“整个”Entity 类进行更新
  3. 如果字段大部分匹配,但有区别——你可以引入Base类和公共字段,然后为适当的情况创建Entity : BaseDto : Base

【讨论】:

    【解决方案2】:

    在 Lanorkin 和 post 的帮助下,我想出了一个可行的解决方案。我创建了包含存储过程调用的字段子集的基类。 Entity 生成的类然后扩展基类添加 ID。为了帮助添加到数据库中,我创建了一个辅助构造函数来使用实体初始化基类的所有成员。我的代码如下:

    namespace LegacyApp.Models
    {
        using System;
        using System.Collections.Generic;
    
        // My base class
        public partial class A
        {
            public Nullable<int> SOId { get; set; }
            public string SODesc { get; set; }
            //... 
        }
    }
    

    我的类由Entity生成

    namespace LegacyApp.Models
    {
        using System;
        using System.Collections.Generic;
    
        public partial class B : A
        {
            /// <summary>
            /// Used to assign all members of base class A to B
            /// </summary>
            /// <param name="baseClass">the base class</param>
            public B(A baseClass) : base()
            {
                foreach (var prop in typeof(A).GetProperties())
                {
                    this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(baseClass, null), null);
                }
            }
            public int? ID { get; set; }
        }
    }
    

    我的控制器

    public class MyController : Controller
    {
        private MyDBContext db = new MyDBContext();
        //...
    
        [HttpPost]
        [ValidateInput(false)]
        [OutputCache(NoStore = true, Duration = 0)]
        public ActionResult Index(ViewModel rb)
        {
            var query = this.buildQuery().ToString();
    
            // The results returned by the query contain all members of B except for ID
            IEnumerable<A> goals = db.Database.SqlQuery<A>(query);
    
            IList<B> goalsToInsert = new List<B>();
            // Create a new List of Objects of type B. 
            // Constructor allows for all members of A to be assigned to B 
            goals.ToList().ForEach(x => {goalsToInsert.Add(new B(x));});
            db.B.AddRange(goalsToInsert);
            db.SaveChanges();
    
            rb.goalList = goalsToInsert;
            return View(rb);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多