Asp.net core mvc 如何将现有实体添加到EF中的新实体?

Asp.net core mvc 如何将现有实体添加到EF中的新实体?,asp.net-core-mvc,entity-framework-core,Asp.net Core Mvc,Entity Framework Core,我目前有两个类相互映射。我收到以下错误: MERGE语句与外键约束冲突 “FK_故事_用户_用户ID”。数据库中发生冲突 “StoriesDb”,表“dbo.Users”,列“Id” 我正在尝试将UserId FK添加到我刚刚创建的新故事实体中。我的类看起来像这样(剪掉了不相关的属性) 公共类故事:ITimestamp { 公共故事(){} 公共int Id{get;set;} 公共字符串说明{get;set;} 公共字符串描述符标记{get;set;} 公共字符串标题{get;set;} 公共

我目前有两个类相互映射。我收到以下错误:

MERGE语句与外键约束冲突 “FK_故事_用户_用户ID”。数据库中发生冲突 “StoriesDb”,表“dbo.Users”,列“Id”

我正在尝试将UserId FK添加到我刚刚创建的新故事实体中。我的类看起来像这样(剪掉了不相关的属性)

公共类故事:ITimestamp
{
公共故事(){}
公共int Id{get;set;}
公共字符串说明{get;set;}
公共字符串描述符标记{get;set;}
公共字符串标题{get;set;}
公共Guid用户标识{get;set;}
公共虚拟用户用户{get;set;}
公共虚拟日期时间CreatedDate{get;set;}
公共虚拟日期时间修改日期{get;set;}
}    
公共类用户:ITimestamp
{
公共Guid Id{get;set;}
公共字符串用户名{get;set;}
公共字符串电子邮件{get;set;}
公共字符串密码哈希{get;set;}
公共字符串密码salt{get;set;}
公共虚拟IList注释{get;set;}=new List();
公共虚拟日期时间CreatedDate{get;set;}
公共虚拟日期时间修改日期{get;set;}
}
我添加如下新故事:

public async Task<StorySummaryViewModel> Create(CreateViewModel model, string username, Guid userId)
{
      var story = await StoriesDbContext.Stories.AddAsync(new Story() {
                Title = model.Title,
                DescriptionMarkdown = model.DescriptionMarkdown,
                Description = CommonMarkConverter.Convert(model.DescriptionMarkdown),
                UserId = userId
      });

      var rowCount = await StoriesDbContext.SaveChangesAsync();
      [...]
}
public Guid UserId { get; set; }

[ForeignKey(nameof(UserId))]
public virtual User User { get; set; }
公共异步任务创建(CreateViewModel模型、字符串用户名、Guid用户ID)
{
var story=await StoriesDbContext.Stories.AddAsync(new story()){
Title=model.Title,
DescriptionMarkdown=model.DescriptionMarkdown,
Description=CommonMarkConverter.Convert(model.DescriptionMarkdown),
UserId=UserId
});
var rowCount=await StoriesDbContext.SaveChangesAsync();
[...]
}
通过其他一些创建方法,我知道将新实体对象添加到第二个新实体的导航属性将正确保存。但是,此时我不希望在保存故事实体时修改用户实体,这就是我设置UserId属性(标记为FK)的原因。但它似乎不起作用

我还将传递给方法的UserId与数据库数据进行了比较,它们都是相同的值

仅设置FK Id属性的技术是我在EF6中使用的,它按预期工作

我的DbContext或映射中是否缺少允许我按外键id保存新实体更改的内容

这个问题很类似于。但不幸的是,它只处理新创建的实体

编辑 我包括了我对故事和用户的映射

public class StoryMap : IEntityTypeConfiguration<Story>
    {
        public void Map(EntityTypeBuilder<Story> builder)
        {
            builder.HasKey(e => e.Id);
            builder.Property(s => s.Url).IsRequired();
            builder.Property(s => s.Title).IsRequired();

            builder.HasOne(e => e.User).WithMany().HasForeignKey(e => e.UserId);
            builder.HasMany(e => e.Comments).WithOne(c => c.Story).HasForeignKey(c => c.StoryId);
            builder.HasMany(e => e.Votes).WithOne(v => v.Story).HasForeignKey(v => v.StoryId);
        }
    }

public class UserMap : IEntityTypeConfiguration<User>
{
    public void Map(EntityTypeBuilder<User> builder)
    {
        builder.HasKey(u => u.Id);
        builder.HasIndex(u => u.Email);

        builder.Property(u => u.PasswordHash).IsRequired();
        builder.Property(u => u.PasswordSalt).IsRequired();
        builder.Property(u => u.Username).IsRequired();
        builder.Property(u => u.Email).IsRequired();

        // Navigation
        [..snip..]
        builder.HasMany(u => u.Stories).WithOne(c => c.User).HasForeignKey(s => s.UserId);
    }
}
公共类故事图:IEntityTypeConfiguration
{
公共空白地图(EntityTypeBuilder)
{
builder.HasKey(e=>e.Id);
属性(s=>s.Url).IsRequired();
builder.Property(s=>s.Title).IsRequired();
HasOne(e=>e.User).WithMany().HasForeignKey(e=>e.UserId);
HasForeignKey(c=>c.StoryId);
HasForeignKey(v=>v.StoryId);
}
}
公共类UserMap:IEntityTypeConfiguration
{
公共空白地图(EntityTypeBuilder)
{
builder.HasKey(u=>u.Id);
builder.HasIndex(u=>u.Email);
属性(u=>u.PasswordHash).IsRequired();
属性(u=>u.PasswordSalt).IsRequired();
builder.Property(u=>u.Username).IsRequired();
builder.Property(u=>u.Email).IsRequired();
//航行
[…剪断..]
HasForeignKey(s=>s.UserId);
}
}
为迁移编辑

migrationBuilder.CreateTable(
                name: "Stories",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    CreatedDate = table.Column<DateTime>(nullable: false),
                    Description = table.Column<string>(nullable: true),
                    DescriptionMarkdown = table.Column<string>(nullable: true),
                    ModifiedDate = table.Column<DateTime>(nullable: false),
                    Title = table.Column<string>(nullable: false),
                    Url = table.Column<string>(nullable: false),
                    UserId = table.Column<Guid>(nullable: false),
                    UserIsAuthor = table.Column<bool>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Stories", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Stories_Users_UserId",
                        column: x => x.UserId,
                        principalTable: "Users",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });
migrationBuilder.CreateTable(
名称:“故事”,
列:表=>new
{
Id=table.Column(可空:false)
.Annotation(“SqlServer:ValueGenerationStrategy”,SqlServerValueGenerationStrategy.IdentityColumn),
CreatedDate=table.Column(可空:false),
Description=table.Column(可空:true),
DescriptionMarkdown=table.Column(可空:true),
ModifiedDate=table.Column(可空:false),
Title=table.Column(可空:false),
Url=table.Column(可空:false),
UserId=table.Column(可空:false),
UserIsAuthor=table.Column(可空:false)
},
约束:表=>
{
表.PrimaryKey(“PK_故事”,x=>x.Id);
表1.外键(
名称:“FK_故事_用户_用户ID”,
列:x=>x.UserId,
原则性:“用户”,
主栏:“Id”,
onDelete:referentialiction.Restrict);
});
我使用了相同的技术(设置
UserId
值而不是full
User
引用),它工作正常,只需添加一项-我在
UserId
User
属性之间使用显式FK绑定,如下所示:

public async Task<StorySummaryViewModel> Create(CreateViewModel model, string username, Guid userId)
{
      var story = await StoriesDbContext.Stories.AddAsync(new Story() {
                Title = model.Title,
                DescriptionMarkdown = model.DescriptionMarkdown,
                Description = CommonMarkConverter.Convert(model.DescriptionMarkdown),
                UserId = userId
      });

      var rowCount = await StoriesDbContext.SaveChangesAsync();
      [...]
}
public Guid UserId { get; set; }

[ForeignKey(nameof(UserId))]
public virtual User User { get; set; }
检查您的数据库(或迁移脚本)-是否可以在您的
故事
中创建两个不同的
用户ID
-类似属性,而不使用此属性


当然,如果愿意,您可以使用fluent API而不是attribute。

看看StoryMap类?看起来还好吗?是的,看起来不错。我从未使用过IEntityTypeConfiguration,但它看起来像是正确的fluent配置。您使用迁移吗?为该实体生成了什么代码?或者,检查SQL DB-FLs看起来像您想要的吗?我添加了创建的迁移,用户表