EF One-to-One更新失败

时间:2018-05-02 19:17:06

标签: c# entity-framework entity-framework-6

我在EF6中定义了一对一的关系,适用于插入。不幸的是,当我尝试使用断开连接的记录进行更新时,我收到错误。以下是详细信息:

.NET来源:

namespace EF_ConsoleApp_Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            int? accountId;
            int? customerId;

            using (var db = new MainContext())
            {
                var account = new Account
                {
                    AccountNumber = "1234",
                    Customer = new Customer {FirstName = "John"}
                };

                db.Accounts.Add(account);
                db.SaveChanges();

                accountId = account.Id;
                customerId = account.Customer.Id;
            }

            using (var db = new MainContext())
            {
                // disconnected record
                var account = new Account()
                {
                    Id = accountId,
                    AccountNumber = "9876",
                    Customer = new Customer() {Id = customerId}
                };

                db.Accounts.Add(account);
                db.Entry(account).State = EntityState.Modified;
                db.Entry(account.Customer).State = EntityState.Unchanged;

                db.SaveChanges(); // Error occurs here
            }
        }

        [Serializable]
        [Table("CUSTOMERS")]
        public class Customer
        {
            [Key] [Column("CUSTOMER_ID")] public int? Id { get; set; }

            [Required]
            [Column("FIRST_NAME")]
            [StringLength(45)]
            public string FirstName { get; set; }

            public virtual Account Account { get; set; }

            public Customer() { }
        }

        [Serializable]
        [Table("ACCOUNTS")]
        public class Account
        {
            [Key]
            [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
            [Column("ACCOUNT_ID")]
            public int? Id { get; set; }

            [Required]
            [Column("ACCOUNT_NUMBER")]
            [Display(Name = "Account Number")]
            [StringLength(16)]
            public string AccountNumber { get; set; }

            public virtual Customer Customer { get; set; }

            /// <summary>
            /// Default Constructor
            /// </summary>
            public Account() { }
        }

        internal class MainContext : DbContext
        {
            internal MainContext() : base("name=ACHRE.Context")
            {
                Database.SetInitializer<MainContext>(null);
            }

            public virtual DbSet<Account> Accounts { get; set; }

            public virtual DbSet<Customer> Customers { get; set; }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                // Configure FK
                modelBuilder.Entity<Customer>()
                    .HasRequired(c => c.Account)
                    .WithRequiredPrincipal(a => a.Customer)
                    .Map(m => m.MapKey("CUSTOMER_ID"));

                base.OnModelCreating(modelBuilder);
            }
        }
    }
}

数据库表创建语句:

CREATE TABLE [dbo].[CUSTOMERS](
    [CUSTOMER_ID] [INT] IDENTITY(1,1) NOT NULL,
    [FIRST_NAME] [varchar](45) NOT NULL,
 CONSTRAINT [PK_CUSTOMERS] PRIMARY KEY CLUSTERED 
(
    [CUSTOMER_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[ACCOUNTS](
    [ACCOUNT_ID] [INT] IDENTITY(1,1) NOT NULL,
    [CUSTOMER_ID] [int] NOT NULL,
    [ACCOUNT_NUMBER] [varchar](16) NOT NULL,
 CONSTRAINT [PK_ACCOUNTS] PRIMARY KEY CLUSTERED 
(
    [ACCOUNT_ID] 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].[ACCOUNTS]  WITH CHECK ADD  CONSTRAINT [FK_ACCOUNTS_CUSTOMERS] FOREIGN KEY([CUSTOMER_ID])
REFERENCES [dbo].[CUSTOMERS] ([CUSTOMER_ID])
GO

错误:

  

来自'Customer_Account'AssociationSet的关系在   '添加'状态。给定多重约束,相应的   'Customer_Account_Target'也必须处于'已添加'状态。

我需要更新哪些才能使其正常工作?

备注

  • 这与之前提到的question相关,与插入有关。插件已解决,但在删除外键时引入了此问题。
  • 使用EF 6.2和.NET 4.7.1。

2 个答案:

答案 0 :(得分:2)

这是因为您要再次添加实体。您需要先调用db.Accounts.Attach(account);来附加对象。

或者更好的方法是首先根据Id获取,然后修改所需的字段,如下所示:

       using (var db = new MainContext())
        {
            var account =  db.Accounts.SingleOrDefault(x => x.id == accountId);
            account.AccountNumber = "9876"
            db.SaveChanges();
        }

答案 1 :(得分:2)

这是db.Accounts.Add(account);电话的副作用。它将一些阴影状态设置为Added,这不能被下一次State操作否定。

提前

Attach在这种情况下不起作用。因此要么使用@Harsh的第二个建议,要么强制更新,请不要致电Add,只需将State的{​​{1}}设置为account即可。这将附加它并将其标记为已修改,不会影响关联的Modified

Customer