当我只想要一个参考时,实体试图创建子实体

时间:2018-06-18 20:34:05

标签: c# asp.net asp.net-core .net-core entity-framework-core

我一直试图弄清楚实体框架核心的ASP.net核心在子实体方面是如何工作的。目前,我的问题是我可以创建一个“SomeThing”实体,将Status作为一个完整的实体,插入两者,但我无法弄清楚如何创建第二个“SomeThing”链接到相同的状态而不会抛出错误说它已经存在了?

以下是我的模型和上下文代码:

主要课程:

public class SomeThing
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int SomeThingId { get; set; }

        public DateTime CreatedDate { get; set; }

        public DateTime? RequestedDate { get; set; }

        [Required(ErrorMessage = "Description is required.")]
        public string Description { get; set; }

        [Required]
        public int CreatedBy { get; set; }

        public bool? Archived { get; set; }

        //Linked items
        [Required(ErrorMessage = "Status is required.")]
        [ForeignKey("StatusCode")]
        public Status Status { get; set; }
    }

儿童班:

public class Status
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public string Code { get; set; }

        [Required(ErrorMessage = "The status requires a description")]
        public string Description { get; set; }

        public Status()
        {
        }
    }

上下文:

public class OCWRContext : DbContext
    {
        public DbSet<Status> Statuses { get; set; }
        public DbSet<SomeThing> WorkRequests { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<SomeThing>(entity =>
            {
                entity.HasKey(st => st.SomeThingId);
                entity.Property<int>("SomeThingId")
                    .ValueGeneratedOnAdd();
                entity.Property<byte[]>("Version")
                    .IsRowVersion();
                entity.HasOne(st => st.Status)
                      .WithMany()
                      .OnDelete(DeleteBehavior.Restrict);
            });

            modelBuilder.Entity<Status>(entity =>
            {
                //entity.HasKey(s => s.Code);
                //entity.HasMany(s => s.Code)
                      //.WithOne();

            });

        } 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseMySQL(connectionString);
        }
    }

我错误地链接了吗?在这个主题上我找不到对我有意义的东西。我来自一个主要的JS背景,之前从未使用过EF,所以我现在只是在圈子里跑。

我目前打电话来创建“SomeThing”是:

POST

{
    "CreatedDate": "2018-06-14",
    "Description": "There's a thing.",
    "CreatedBy": 1,
    "Archived": 0,
    "Status": {
        "Code": "1000",
        "Description": "test"
    }
}

让我再次朝着正确的方向前进的任何帮助都非常感谢!如果您需要我提供的任何其他信息,请告诉我们。我现在很想弄清楚这一点。

提前致谢,

史蒂夫

1 个答案:

答案 0 :(得分:1)

  

如何创建第二个“SomeThing”链接到相同的状态,而不会抛出错误表明它已经存在

您遇到的问题称为Disconnected Entities

  

...有时使用一个上下文实例查询实体,然后使用其他实例保存。

     

...在这种情况下,第二个上下文实例需要知道实体是新的(应该插入)还是现有的(应该更新)。

在您的情况下,如果数据库已有Status Code == "A",则您无法添加new Status Code。如果不改变你的背景或模型你可以做的事情是这样的:

  1. Find StatusCode
  2. 如果未找到Status,则创建new Status
  3. 将步骤1或2中的Status设置为new SomeThing
  4. 上述步骤的示例代码:

    using (var context = new OCWRContext())
    {
        string statusCode = "A";
    
        Status status =
            context.Statuses.Find(statusCode) //Step 1
            ?? context.Statuses.Add(new Status { Code = statusCode, Description = "" }).Entity; //Step 2
    
        var someThing = new SomeThing
        {
            Status = status, //Step 3
            Description = ""
        };
    
        context.Add(someThing);
        context.SaveChanges();
    }