下面的示例1用于工作,但它在EF Core中不起作用。 问题:如何让下面的示例2工作?
示例1 :
child c1 = new child();
child c2 = new child();
parent p=new parent();
p.child.Add(c1);
p.child.Add(c2);
using (var db = new DbContext())
{
db.parent.Add(p);
db.SaveChanges();
}
实体父P具有子C1和C2一对一的关系。尝试插入父级及其子记录。但在下面的代码中,VS2017
的编辑intellisense
无法在.child
行识别cust.child.Add(c1);
。也许,EF Core有更好的插入父/子记录。我正在使用ASP.NET MVC Core 1.1.1
和EF Core 1.1.1。
示例2 :
...
Parent p = new Parent { Name = "some name" , FY = SelectedYear, ... };
Child c1 = new Child { ItemName = "Abc"};
Child c2 = new Child { ItemName = "Rst"};
p.child.Add(c1);
p..child.Add(c2);
_context.Add(p);
_context.SaveChanges();
更新:
根据@GlennSills
的请求,以下是众所周知的Blogging Db示例(摘自this ASP.NET教程):
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
在下面Create(...)
方法的第blog.Posts.Add(c);
行,我收到错误:Object reference not set to an instance of an object.
public class BlogsController : Controller
{
private readonly BloggingContext _context;
public BlogsController(BloggingContext context)
{
_context = context;
}
....
....
// POST: Blogs/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("BlogId,Url")] Blog blog)
{
if (ModelState.IsValid)
{
Post c = new Post();
blog.Posts.Add(c);
_context.Add(blog);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(blog);
}
}
答案 0 :(得分:1)
保存子对象及其父对象一定有效。关键是您需要以EF了解所有关系的方式对您的实体进行建模。这是一个非常简单的应用程序,你可以看看。 Simple app on github
我有一个看起来像
的父母using System.Collections.Generic;
namespace EFParentChild
{
public class Parent
{
public int ParentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Child> Children { get; set; } = new List<Child>();
}
}
这里的孩子
namespace EFParentChild
{
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
以下是上下文:
使用Microsoft.EntityFrameworkCore;
namespace EFParentChild
{
class DbParentChild : DbContext
{
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ParentChildDb;Trusted_Connection=True;");
}
}
}
以下是保存数据的程序
static void Main(string[] args)
{
using (var dbContext = new DbParentChild())
{
var parent = new Parent
{
FirstName = "Joe",
LastName = "Smith"
};
parent.Children.Add(
new Child
{
FirstName = "LittleJoe",
LastName = "Smith"
});
parent.Children.Add(
new Child
{
FirstName = "Anne",
LastName = "Smith"
});
dbContext.Add(parent);
dbContext.SaveChanges();
}
}
这里的关键是我使用惯例告诉EF有父子关系。注意两个实体之间使用的id名称是如何匹配的。该子项具有与其父项中的ParentId匹配的ParentId。还注意到了孩子的外键约束。
我使用实体框架工具创建了表格。您可以自己采取这种方法,或者如果您愿意,可以手工创建。父DDL是:
CREATE TABLE [dbo].[Parents] (
[ParentId] INT IDENTITY (1, 1) NOT NULL,
[FirstName] NVARCHAR (MAX) NULL,
[LastName] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_Parents] PRIMARY KEY CLUSTERED ([ParentId] ASC)
);
孩子DDL是:
CREATE TABLE [dbo].[Children] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[FirstName] NVARCHAR (MAX) NULL,
[LastName] NVARCHAR (MAX) NULL,
[ParentId] INT NOT NULL,
CONSTRAINT [PK_Children] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Children_Parents_ParentId] FOREIGN KEY ([ParentId])
REFERENCES [dbo].[Parents] ([ParentId]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_Children_ParentId]
ON [dbo].[Children]([ParentId] ASC);
答案 1 :(得分:-1)
我假设你有父实体的自动生成id,在这种情况下你需要将父实体添加到DbSet并保存更改,以便EF Core设置生成的属性值。
尝试此代码,您将保存信息:
// Create instance for parent class
var p = new Parent { Name = "some name", FY = SelectedYear, ... };
// Add entity instance to db context
_context.Parent.Add(p);
// Save changes, this action sets the generated id value to entity's property
_context.SaveChanges();
// Create instances for child entities
var c1 = new Child { ItemName = "Abc", ParentID = p.ParentID };
var c2 = new Child { ItemName = "Rst", ParentID = p.ParentID };
// Add child to db context
_context.Child.Add(c1);
_context.Child.Add(c2);
// Save changes
_context.SaveChanges();
似乎保存失败,因为每个子实例都没有ParentID属性的值,并且该列不允许空值。
让我知道这是否有用