0

我正在尝试做某事,这是一个“演示”,非常简单的示例。(这个演示没有意义,但它让我大致了解了我正在尝试做的事情)

我评论了我尝试过的内容

有没有办法在不创建新上下文的情况下做到这一点?

这是 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);
}
4

1 回答 1

1

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

当您再次创建查找实例时,它是 .NET 中的不同实例,但对于数据库/EF,它实际上是重复的。

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

于 2014-03-29T01:08:14.293 回答