实体框架-具有多对多映射的插入模型 [英] Entity Framework - Inserting model with many to many mapping

查看:62
本文介绍了实体框架-具有多对多映射的插入模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我具有这样的模型设置时,如何插入属于模型 Post 的模型 Tag

How can I insert a model Tag that belongs to a model Post when I have the models setup like this:

发布

public class Post
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }
    public Post()
    {
       Tags = new List<Tag>();
    }
}

标记

public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
}

此问题建议创建一个Post对象,然后将Tags添加到Tags集合,我无法正常运行:
插入/更新多对多实体框架。我该怎么做?

This question suggests to create a Post object then add Tags to the Tags collection, I couldn't get it working: Insert/Update Many to Many Entity Framework . How do I do it?

我想在数据库中已经将Tag添加到Post,我该如何使用EF。我是EF的新手。

I want to add Tag to Post already in the database, how can I do that with EF. I'm new to EF.

这是我尝试过的方法,如果将其发送到API,则不会插入任何记录,并且可以看到新的 tag Id = 0 在数据库中不存在,但是我认为这会导致外键约束错误,不确定是否需要执行某些操作为标签自动生成ID:

This is what I've tried, if I send this to the API it doesn't insert any records and I can see that the new tag Id = 0 which doesn't exist in the database, but I'd think that'd cause a foreign key constraint error, not sure If I need to do something to auto generate Id for the tag:

{
    Name: "test"
}

API

[ResponseType(typeof(Tag))]
public IHttpActionResult PostTag(Tag tag)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var post = new Post();
    var tags = new List<Tag>();
    tags.Add(tag);

    post.Tags.Add(tag);
    post.Id = 10;
    db.Entry(post).State = EntityState.Modified;
    db.SaveChanges();

    return CreatedAtRoute("DefaultApi", new { id = tag.Id }, tag);
}


推荐答案

如果您说有多对多关系,其中 PostTag Tag Post ,那么您的模型没有显示任何多对多关系,所以从我的情况来看看到在 Post Tag之间有
一对多 code>,因为您的模型定义。

If you said there is Many-To-Many relation which the PostTag is connection table between Tag and Post then your models don't show any many-to-many relation, so from what I have seen there is one-to-many between Post and Tag because of your model definition.

如果要建立多对多关系在它们之间,您必须执行以下操作:

if you want to make many-to-many relation between them you have to something like below:

public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
    public Tag()
    {
        Posts = new HashSet<Post>();
    }
} 
public class Post
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual ICollection<Tag> Tags { get; set; } 
    public Post()
    {
        Tags = new HashSet<Tag>();
    }
}

OnModelCreating 通过fluent api建立联系,如下所示:

and in OnModelCreating make relation by fluent api as below :

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ 
    modelBuilder.Entity<Tag>()
        .HasMany(s => s.Posts)
        .WithMany(c => c.Tags)
        .Map(cs =>
        {
            cs.MapLeftKey("TagId");//TagId
            cs.MapRightKey("PostId");//PostId
            cs.ToTable("PostTag");
        });
}

反之亦然

modelBuilder.Entity<Post>()
    .HasMany(s => s.Tags)
    .WithMany(c => c.Posts)
    .Map(cs =>
        {
            cs.MapLeftKey("PostId");//PostId
            cs.MapRightKey("TagId");//TagId
            cs.ToTable("PostTag");
        });

您可以看到并知道应该有一个名为 PostTag的表有两列作为键,这些脚本具有以下脚本:

as you can see and know there should be a table named PostTag in database which have two columns as keys which have a script like :

CREATE TABLE [dbo].[PostTag](
    [TagId] [int] NOT NULL,
    [PostId] [int] NOT NULL,
 CONSTRAINT [PK_PostTag] PRIMARY KEY CLUSTERED 
(
    [TagId] ASC,
    [PostId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] 

ALTER TABLE [dbo].[PostTag]  WITH CHECK ADD  CONSTRAINT [FK_PostTag_Post] FOREIGN KEY([PostId])
REFERENCES [dbo].[Post] ([Id])
GO 
ALTER TABLE [dbo].[PostTag] CHECK CONSTRAINT [FK_PostTag_Post]
GO 
ALTER TABLE [dbo].[PostTag]  WITH CHECK ADD  CONSTRAINT [FK_PostTag_Tag] FOREIGN KEY([TagId])
REFERENCES [dbo].[Tag] ([TagId])
GO 
ALTER TABLE [dbo].[PostTag] CHECK CONSTRAINT [FK_PostTag_Tag]
GO

看看此处以获取更多信息。

更新:

如果要建立零对多关系, code> Post Tag ,则模型应如下所示:

if you want establish zero-to-many relation between Post and Tag then the models should be like below:

public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? PostId { get; set; }
}
public class Post
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }
    public Post()
    {
        Tags = new HashSet<Tag>();
    }
}

以及与流利api的一对多关系:

and one to many relation with fluent api :

modelBuilder.Entity<Post>()
   .HasMany(o1 => o1.Tags);

作为您的注释,您不需要 Tag 具有导航属性,因此如果存在关联,则应在 Tag 中将其定义为 Nullable 这是伪键在它们之间,您至少应该通过Navigation属性或 Nullable 属性建立关系。

as your comment you don't want Tag have navigate property so you should define a property as Nullable in Tag which is feign key, if there is a relation between them you should establish relation at least by navigate property or Nullable property.

正确答案来自此处(无更改):
如果您想为存在的帖子分配标签,则应该先找到该帖子,然后再向其中添加标签标签确实存在于数据库中,将在Tag和发现的Post之间建立关系,如果该Tag不存在,则将标签插入数据库,

The correct answer came from here (with no change): You want to assign a tag to exist post you should find that Post firstly then add a tag to it, if that tag does exist in DB a relation will be made between Tag and found Post if that Tag does not exist then Tag will be inserted to DB,

看看这个:

var post = context.Posts.SingleOrDefault(x => x.Id == 4);//That Id would be you specific Post Id
var existTag = context.Tags.SingleOrDefault(x => x.Id == 1); //Exist Tag in DB
post.Tags.Add(existTag);
context.SaveChanges();
//Inserting new tag to DB and assign it to Post also
Tag newTag = new Tag // Does not exist in DataBase
{
    Name = "tag2"
};
post.Tags.Add(newTag);// By this tag2 will be insert into Tag table first and then added to post (insert new record to PostTag)
context.SaveChanges();

这篇关于实体框架-具有多对多映射的插入模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆