2017-10-01 9 views
0

以下の例1は動作していましたが、EFコアでは機能しません。 質問:下記の例2をどのようにするには?EFコアに子レコードを持つ親レコードを追加する方法

例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は、1対1の関係で子供C1、及びC2を有しています。親レコードとその子レコードを挿入しようとしています。しかし、次のコードVS2017のエディタのintellisenseは、の.childを認識しません。おそらく、EFコアには、親子レコードを挿入するための優れた機能があります。私はASP.NET MVC Core 1.1.1とEFコア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(); 

UPDATE@GlennSillsから要求ごと

、以下ではよく知られているブログ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; } 
} 

以下方法は、ライン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

はあなたがEFコアでトランザクションを使用してみましたか? –

+0

@ H.Herzlいいえ、私はしていません。それはどんなものでしょうか? – nam

+0

あなたはアイデンティティを使用していますか? –

答えて

-1

私はあなたがあなたがDbSetに親エンティティを追加し、するために、変更内容を保存する必要があり、その場合には、親エンティティのIDを自動生成していると仮定しています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プロパティの値を持っていないと、その列がnull値を許可しないため、保存が失敗したように思え。これは便利である場合

私に教えてください

+0

親と子の両方が同一性を持つPKを持っています。また、子テーブルのFKはNULL可能です。その場合、提案されたソリューションの敷居は大丈夫でしょうか? – nam

+0

はい、各変更保存呼び出しでID値が生成されるため、 –

+0

'_context.Parents.Add(p);'行に「MyProjContextに親の定義がありません」というエラーが表示されます。 MyProjContextは普通のクラス 'パブリッククラスMyProjContextある:DbContext {公共MyProjContext(DbContextOptions オプション):ベース(オプション) { }公共DbSet 親{得ます。セット; } public DbSet 子{get;セット; } ' – nam

0

の保存子は親間違いなく作品と一緒にオブジェクト。キーは、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; } 
    } 
} 

だ持っているがコンテキストです:マイクロソフトを使用して

。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を伝えるための規則を使用しているということです。 2つのエンティティ間で使用される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);