实体框架6.1检查,如果没有附加,则附加崩溃

本文关键字:框架 崩溃 如果没有 检查 实体 | 更新日期: 2023-09-27 17:54:35

我想做点什么,这里是一个"demo",非常简单的例子。(这个演示没有意义,但它给了我一个大概的想法,我要做什么)

i comment out what i have try

是否有一种方法可以在不创建新上下文的情况下做到这一点?

this is database first on SQL server

c#代码
using System;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //remove then add it back, without select from the db
            using (var db = new testing())
            {
                var lookup = new edmx.LookupTable() { LookupId = 1 };
                var main = new edmx.MainTable() { MainId = 10 };
                main.LookupTables.Add(lookup);
                db.LookupTables.Attach(lookup);
                db.MainTables.Attach(main);
                main.LookupTables.Remove(lookup);
                db.SaveChanges();
                //imagine this is a loop from n to m and it happen that you have to add back something that you just deleted
                lookup = new edmx.LookupTable() { LookupId = 1 };
                //crash if nothing
                //db.Entry(lookup).State = EntityState.Unchanged; //crash
                //db.LookupTables.Attach(lookup); //crash
                if (!db.context.IsAttachedTo(lookup))
                {
                    //db.Entry(lookup).State = EntityState.Unchanged; //crash
                    //db.LookupTables.Attach(lookup); //crash
                }
                bool isDetached = db.Entry(lookup).State == EntityState.Detached;
                if (isDetached)
                {
                    //db.Entry(lookup).State = EntityState.Unchanged; //crash
                    //db.LookupTables.Attach(lookup); //crash
                }
                main.LookupTables.Add(lookup);
                db.SaveChanges();
            }
            Console.ReadKey();
        }
    }
    public partial class testing : edmx.testingEntities
    {
        public testing()
            : base()
        {
            this.Database.Log = x => System.Diagnostics.Debug.Write(x);
        }
        public ObjectContext context
        {
            get { return (this as IObjectContextAdapter).ObjectContext; }
        }
    }
    public static class helper
    {
        public static bool IsAttachedTo(this ObjectContext context, object entity)
        {
            ObjectStateEntry entry;
            if (context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry))
            {
                return (entry.State != EntityState.Detached);
            }
            return false;
        }
    }
}
SQL脚本

USE [testing]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[LookupTable](
    [LookupId] [int] NOT NULL,
 CONSTRAINT [PK_LookupTable] PRIMARY KEY CLUSTERED 
(
    [LookupId] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MainTable](
    [MainId] [int] NOT NULL,
 CONSTRAINT [PK_MainTable] PRIMARY KEY CLUSTERED 
(
    [MainId] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MainTable_LookupTable](
    [MainId] [int] NOT NULL,
    [LookupId] [int] NOT NULL,
 CONSTRAINT [PK_MainTable_LookupTable] PRIMARY KEY CLUSTERED 
(
    [MainId] ASC,
    [LookupId] 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
INSERT [dbo].[LookupTable] ([LookupId]) VALUES (1)
GO
INSERT [dbo].[MainTable] ([MainId]) VALUES (10)
GO
INSERT [dbo].[MainTable_LookupTable] ([MainId], [LookupId]) VALUES (10, 1)
GO
ALTER TABLE [dbo].[MainTable_LookupTable]  WITH CHECK ADD  CONSTRAINT [FK_MainTable_LookupTable_LookupTable] FOREIGN KEY([LookupId])
REFERENCES [dbo].[LookupTable] ([LookupId])
GO
ALTER TABLE [dbo].[MainTable_LookupTable] CHECK CONSTRAINT [FK_MainTable_LookupTable_LookupTable]
GO
ALTER TABLE [dbo].[MainTable_LookupTable]  WITH CHECK ADD  CONSTRAINT [FK_MainTable_LookupTable_MainTable] FOREIGN KEY([MainId])
REFERENCES [dbo].[MainTable] ([MainId])
GO
ALTER TABLE [dbo].[MainTable_LookupTable] CHECK CONSTRAINT [FK_MainTable_LookupTable_MainTable]
GO

的解决方案,在我的情况下,是这个代码

for (var i = 1; i < 3; ++i)
{
    lookup = db.LookupTables.Local.FirstOrDefault(x => x.LookupId == i);
    if (lookup == null)
    {
        lookup = new edmx.LookupTable() { LookupId = i };
        db.LookupTables.Attach(lookup);
    }
    main.LookupTables.Add(lookup);
}

实体框架6.1检查,如果没有附加,则附加崩溃

查找实例(id为1)仍然附加到EF,您正在调用的Remove只是删除main(10)和lookup(1)之间的链接。

当你再次创建查找实例时,它在。net中是一个不同的实例,但对于数据库/EF来说,它实际上是一个副本。

您应该重用以前的查找实例,或者使用DbSet的Local属性重新找到它。