首页 > 解决方案 > 实体框架未在 1:0..1 关系中插入相关记录(意外结果)

问题描述

自从我上一篇文章以来已经有一段时间了,这次我需要一些帮助来理解 C# 中使用 Code-First 方法的实体框架(SQL Server)正在发生的事情。

让我向您展示我拥有的代码:

博客.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Helper.Models
{
    public class Blog
    {
        [Key]
        public int BlogId { get; set; }
        public string BlogTitle { get; set; }
        public virtual ICollection<Post> Posts { get; set; }
        public virtual Author Author { get; set; }
    }
}

作者.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Helper.Models
{
    public class Author
    {
        [Key,ForeignKey("Blog")]
        public int AuthorId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public virtual Blog Blog { get; set; }
    }
}

正则作者.cs

using System;

namespace Helper.Models
{
    public class RegularAuthor : Author
    {
        public DateTime DateOfFirstBlogPost { get; set; }
    }
}

来宾作者.cs

namespace Helper.Models
{
    public class GuestAuthor : Author
    {
        public string OriginalBlogAccess { get; set; }
    }
}

DefaultDB.cs

using Helper.Models;
using System.Data.Entity;

    namespace EF_Basics
    {
        public class DefaultDB : DbContext
        {
            public DefaultDB(): base("EFDemo")
            {

            }
            public DbSet<Blog> Blogs { get; set; }
            public DbSet<Post> Posts { get; set; }
            public DbSet<Category> Categories { get; set; }
            public DbSet<Author> Authors { get; set; }
        }
    }

程序.cs

using Helper.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace EF_Basics
{
    class Testing
    {
        static void Main(string[] args)
        {
            TestInsert2();
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }

        private static void TestInsert2()
        {
            using (DefaultDB ctx = new DefaultDB())
            {
                RegularAuthor author1 = new RegularAuthor()
                {
                    Name = "First Author",
                    Address = GetLocalIpAddress(),
                    DateOfFirstBlogPost = DateTime.Now
                };

                GuestAuthor guest1 = new GuestAuthor()
                {
                    Name = "Second Author",
                    Address = GetLocalIpAddress(),
                    OriginalBlogAccess = "Never"
                };

                List<Blog> BlogList = new List<Blog>()
                {
                    new Blog
                    {
                        Author = author1,
                        BlogTitle = "Mid Century Modern DIY Dog House Build"
                    },
                    new Blog
                    {
                        Author = guest1,
                        BlogTitle = "Elf Doughnut Box Printable"
                    },
                    new Blog
                    {
                        Author = author1,
                        BlogTitle = "5 Ways to Make Giant Candy for a Candyland Theme"
                    }
                };

                foreach (var blog in BlogList)
                {
                    Console.WriteLine($"Adding '{blog.BlogTitle}' by '{blog.Author.Name}'");
                    ctx.Blogs.Add(blog);
                    Thread.Sleep(1000);
                    Console.WriteLine();
                }

                ctx.SaveChanges();
            }
        }

        private static string GetLocalIpAddress()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("No network adapters with an IPv4 address in the system!");
        }
    }
}

所以......现在我们有了所有相关的代码,当我运行它时,所有的“大部分”信息都会进入数据库,但最后一条记录只是忽略了所有的作者数据。我还包括了 SQL 的快照和运行代码后的结果。

来自数据库的 SQL 和结果数据的快照

标签: c#sql-serverentity-framework

解决方案


我认为问题在于您正在将博客添加到数据库中。相反,您应该添加作者及其博客列表。

作者类应该有一个博客列表,因此当您添加作者实体时,您可以根据需要添加任意数量的博客。

public List<Blog> Blogs { get; set; }

在 Blog 类中,您可以更改以下内容:

public Author Author { get; set; }

这是应该做的一个例子:

    private static void TestInsert2()
    {
     using (DefaultDB ctx = new DefaultDB())
     {
       RegularAuthor author1 = new RegularAuthor()
       {
         Name = "First Author",
         Address = GetLocalIpAddress(),
         DateOfFirstBlogPost = DateTime.Now
       };
       GuestAuthor guest1 = new GuestAuthor()
       {
        Name = "Second Author",
        Address = GetLocalIpAddress(),
        OriginalBlogAccess = "Never"
       };

    author1.Blogs = new List<Blog>
    {
       new Blog        
       {
         Author = author1,
         BlogTitle = "Mid Century Modern DIY Dog House Build"
       },
        new Blog
       {
         Author = author1,
         BlogTitle = "5 Ways to Make Giant Candy for a Candyland Theme"
       }
    }

    guest1.Blogs = new List<Blog>
    {
       new Blog
       {
         Author = guest1,
         BlogTitle = "Elf Doughnut Box Printable"
       }
    }
    context.Add(author1);
    context.Add(guest1);
    ctx.SaveChanges();
    }
   }

由于博客被作者对象中的 Blog 属性引用,它们将被添加到数据库中

编辑:

这需要一些努力,但我认为我有解决方案。表关系不正确。

您要做的是让作者拥有许多博客。现在这意味着作者对象必须有一个博客集合。

您必须拥有的关系如下:

在此处输入图像描述

在这种情况下,博客对作者有一个外键,正如我的主要答案中所建议的,作者类必须有一个博客集合:

public partial class Author
{  
    public Author()
    {
        Blogs = new HashSet<Blog>();
    }
    public int authorId { get; set; }
    public string name { get; set; }
    public virtual ICollection<Blog> Blogs { get; set; }
}

同时博客类:

public partial class Blog
{
    public int blogId { get; set; }
    public string blogTitle { get; set; }
    public int? authorId { get; set; }
    public virtual Author Author { get; set; }
}

您的模型将是:

   public Model1()
    {
    }

    public virtual DbSet<Author> Authors { get; set; }
    public virtual DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Author>()
            .Property(e => e.name)
            .IsUnicode(false);

        modelBuilder.Entity<Blog>()
            .Property(e => e.blogTitle)
            .IsUnicode(false);
    }

在运行代码之前:

在此处输入图像描述

运行代码后:

在此处输入图像描述


推荐阅读