c# - 实体框架未在 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 的快照和运行代码后的结果。
解决方案
我认为问题在于您正在将博客添加到数据库中。相反,您应该添加作者及其博客列表。
作者类应该有一个博客列表,因此当您添加作者实体时,您可以根据需要添加任意数量的博客。
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);
}
在运行代码之前:
运行代码后:
推荐阅读
- c# - TimeSpan 属性的有效值可在 Web api 中发布吗?C#
- python - Python-Flask Json 序列化用于从数据库获取操作
- c - 是否可以在格式字符串攻击中将 0 写入变量?
- hyperledger-fabric - 部署在不同服务器上的 Hyperledger Fabric Node.js 客户端应用程序
- q# - Q# ResourcesEstimator 用于 1000 多个量子比特系统的量子化学
- angular - 将先前的值与输出发射器和 ValueChanges 进行比较
- vb.net - 我可以向没有窗口的孤立命令行进程发送命令吗?
- c# - 我目前正在开发一款游戏,但是我正在尝试发表 Else 声明,但它不起作用
- angular - 无法读取未定义的属性“”
- html - 从单击后显示的隐藏菜单中提取 WEB PAGE 数据