【问题标题】:C# Entity Framework - Code First - Data Object Property Resolves NullC# 实体框架 - 代码优先 - 数据对象属性解析 Null
【发布时间】:2013-09-13 17:51:07
【问题描述】:

我正在开发一个多层的 ASP.NET MVC Web 应用程序,但由于无法在我的应用程序中检索我的数据的准确对象表示,因此无法取得进一步进展。 为什么会这样?我已尽量详细说明,但如果您想了解更多信息,请要求澄清。我的项目如下:


-MyProject.Data
-MyProject.Logic
-MyProject.Objects
-MyProject.Web



我的实体类来自 MyProject.Objects.Entities

public class Report
{
    [Key]
    public int Id { get; set; }
    public string ReportName { get; set; }
    public int ProductId { get; set; }
}

public class Product
{
    [Key]
    public int Id { get; set; }
    public string ProductName { get; set; }
    public ICollection<Report> ProductReports { get; set; }
}



来自 MyProject.Data

的我的上下文
public class MyDb : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<Report> Reports { get; set; }
}



我的控制器来自 MyProject.Web

 public class HomeController : Controller
{
    MyDb _db = new MyDb();

    public ActionResult Index()
    {
        var model =
            from p in _db.Products
            orderby p.ProductName ascending
            select p;

        return View(model);
    }
}



最后,我的 Seed() 方法来自 MyProject.Data.Migrations.Configuration

protected override void Seed(MyProject.Data.MyDb context)
    {
        context.Products.AddOrUpdate(r => r.ProductName,
                new Product
                {
                    ProductName = "AAA",
                    ProductReports =
                        new List<Report> { 
                            new Report { ReportName = "Report A" },
                            new Report { ReportName = "Report B" },
                            new Report { ReportName = "Report C" }
                            }
                },
                new Product
                {
                    ProductName = "MSI",
                    ProductReports =
                        new List<Report> { 
                            new Report { ReportName = "Report X" },
                            new Report { ReportName = "Report Z" }
                            }
                });
    }




我不知道为什么我无法从 MyProject.Objects.Entities.Product 获取ICollection&lt;Report&gt; ProductReports 以填充正确的值。这是我在 MyProject.Web

中来自Index() 的结果



起初我对这个框架有点陌生,我认为我遇到了一些与数据结构相关的问题。据我所知,我的数据似乎设置正确。这是我在 SQL Server 中的数据




为了进一步证明数据似乎是正确的,我运行了以下查询以确保关系设置正确。我将在查询旁边提供结果。

SELECT * From Reports INNER JOIN Products ON Reports.ProductId = Products.Id


【问题讨论】:

  • 看起来您实际上从未定义过两个实体之间的映射。没有那个代码吗?
  • 也许吧。我的项目中没有任何类型的映射代码。我还没有看到这样的例子。我会调查一下,谢谢@wilso132

标签: c# .net asp.net-mvc entity-framework n-tier-architecture


【解决方案1】:

如前所述,您似乎缺少映射:

public class Product
{
  [Key]
  public int ProductID { get; set; }
  public string ProductName { get; set; }
  public virtual ICollection<Report> ProductReports { get; set; }
}

public class Report
{
  [Key]
  public int ReportID { get; set; }
  public string ReportName { get; set; }
  public int ProductID { get; set; }
  public virtual Product Product { get; set; }
}

两个表中的映射字段名称必须相同,并且映射将使用 EF 自动为您完成。您还可以向报表添加虚拟属性,以便在报表中调用 Product.ProductName 或其他名称。

希望对你有帮助

【讨论】:

  • 我已尝试实施您的解决方案,重构我的命名约定并包括虚拟属性。但是,我仍然收到 ProductReports 的空结果
  • 优秀。我只是将其包括在内,现在正在恢复我预期的结果。感谢您的贡献。
【解决方案2】:

应该是这样的:

public class ReportMap : EntityTypeConfiguration<Report>
    {
        public ReportMap()
        {
            // Primary Key
            this.HasKey(t => t.Id);

            // Properties
            this.Property(t => t.ReportName)
                .IsRequired()
                .HasMaxLength(100);

            // Table & Column Mappings
            this.ToTable("Reports");
            this.Property(t => t.Id).HasColumnName("Id");
            this.Property(t => t.ReportName).HasColumnName("ReportName");

            // Relationships
            this.HasRequired(t => t.Product)
                .WithMany(t => t.ProductReports)
                .HasForeignKey(d => d.ProductId);
        }
    }

并将您的报告更改为也具有 Product 属性,如下所示:

public class Report
{
    [Key]
    public int Id { get; set; }
    public string ReportName { get; set; }
    public int ProductId { get; set; }
    public virtual Product Product { get; set; }
}

那么在你的上下文中:

public partial class SomeContext : DbContext
{
    static SomeContext()
    {
        Database.SetInitializer<SomeContext>(null);
    }

    public SomeContext()
        : base("Name=SomeContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ReportMap());
    }
}

【讨论】:

  • 顶部的映射是您要查找的内容,尤其是关系部分。您已经通过属性定义了键和诸如此类的东西,这只是一种不同的方法。
  • 所以我需要为我希望设置关系的每个实体创建一个映射类?我认为 EF 的秘诀在于,如果命名正确,事情的简单性就是“正常工作”。
  • @scniro 仅当您需要以特定方式定义关系时。 Jay 提供的答案显示了如何建立自动关系,但它通常无法辨别 HasRequired、HasOptional、HasMany 中的几个选项。
  • 感谢您的进一步解释。我现在可以看到覆盖自动设置的好处。 Jay 还将我的 ICollection ProductReports 标记为虚拟的,这对我有用。
【解决方案3】:

这是我工作的 EF 关系示例:

public class CourseSection
{
    [Key]
    public int CourseSectionID { get; set; }

    public int CourseID { get; set; }

    public string Title { get; set; }

    public virtual ICollection<SectionContent> SectionContents { get; set; }
}

public class Course
{
    [Key]
    public int CourseID { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    public virtual ICollection<CourseSection> CourseSections { get; set; }
}

【讨论】:

  • 当类名在 ID 之前,如 ProductID 等,实体框架会自动分配为外键
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多