草庐IT

c# - Entity Framework 5 升级后多对多关系左右键翻转

coder 2024-05-25 原文

我有一些代码可以在代码中保存多对多关系。它在 Entity Framework 4.1 上运行良好,但在更新到 Entity Framework 5 后,它失败了。

我收到以下错误:

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_WebUserFavouriteEvent_Event". The conflict occurred in database "MainEvents", table "dbo.Event", column 'Id'.

我正在使用带有自定义映射的 POCO 实体。标准字段和多对一关系映射似乎工作正常。

更新

好吧,我已经安装了 SQL Profiler,并且情节已经变厚了......

exec sp_executesql N'insert [dbo].[WebUserFavouriteEvent]([WebUserId], [EventId])
values (@0, @1)
',N'@0 int,@1 int',@0=1820,@1=14

这意味着:

WebUserId = @0 = 1820
EventId = @1 = 14

有趣的是,EF5 似乎翻转了外键...WebUserId 应该是 14EventId 应该是 1820,而不是像现在这样反过来。

我检查了映射代码,99% 的设置都正确无误。参见 Entity Framework Fluent API - Relationships MSDN article获取更多信息。

注意:我还发现这不仅限于保存,SELECT 也会损坏。

以下是所有相关代码:

服务层

public void AddFavEvent(WebUser webUser, Event @event)
{
    webUser.FavouriteEvents.Add(@event);

    _webUserRepo.Update(webUser);
}

存储库

public void Update<T>(params T[] entities)
    where T : DbTable
{
    foreach (var entity in entities)
    {
        entity.UpdatedOn = DateTime.UtcNow;
    }

    _dbContext.SaveChanges();
}

注意:我使用每个请求 1 个 DataContext 方法,因此 webUser@event 会从相同的上下文加载作为 _webUserRepo 中的那个。

实体(不用担心 DbTable 的东西)

public class Event : DbTable
{
    //BLAH
    public virtual ICollection<WebUser> FavouriteOf { get; set; }
    //BLAH
}

public class WebUser : DbTable
{
    //BLAH
    public virtual ICollection<Event> FavouriteEvents { get; set; }
    //BLAH
}

映射

public class EventMapping : DbTableMapping<Event>
{
    public EventMapping()
    {
        ToTable("Event");
        //BLAH
        HasMany(x => x.FavouriteOf)
            .WithMany(x => x.FavouriteEvents)
            .Map(x =>
                     {
                         x.MapLeftKey("EventId");
                         x.MapRightKey("WebUserId");
                         x.ToTable("WebUserFavouriteEvent");
                     });
    }
}

public class WebUserMapping : DbTableMapping<WebUser>
{
    public WebUserMapping ()
    {
        HasMany(x => x.FavouriteEvents)
            .WithMany(x => x.FavouriteOf)
            .Map(m =>
                     {
                         m.MapLeftKey("WebUserId");
                         m.MapRightKey("EventId");
                         m.ToTable("WebUserFavouriteEvent");
                     });
    }
}

最佳答案

看着这个,我怀疑问题可能是由于您将相同的关系映射了两次而引起的。并且您以不同的顺序映射它。

我做了一个简单的测试,我首先映射了一次关系:

    class Program
{
    static void Main(string[] args)
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
        var p = new Parent();
        var c = new Child();
        using (var db = new Context())
        {
            db.Parents.Add(new Parent());
            db.Parents.Add(p);

            db.Children.Add(c);
            db.SaveChanges();
        }

        using (var db = new Context())
        {
            var reloadedP = db.Parents.Find(p.ParentId);
            var reloadedC = db.Children.Find(c.ChildId);

            reloadedP.Children = new List<Child>();
            reloadedP.Children.Add(reloadedC);

            db.SaveChanges();
        }

        using (var db = new Context())
        {
            Console.WriteLine(db.Children.Count());
            Console.WriteLine(db.Children.Where(ch => ch.ChildId == c.ChildId).Select(ch => ch.Parents.Count).First());
            Console.WriteLine(db.Parents.Where(pa => pa.ParentId == p.ParentId).Select(pa => pa.Children.Count).First());
        }
    }
}

public class Parent
{
    public int ParentId { get; set; }
    public ICollection<Child> Children { get; set; }

}

public class Child
{
    public int ChildId { get; set; }
    public ICollection<Parent> Parents { get; set; }
}

public class Context : DbContext
{
    public Context() : base("data source=Mikael-PC;Integrated Security=SSPI;Initial Catalog=EFTest")
    {

    }

    public IDbSet<Child> Children { get; set; }
    public IDbSet<Parent> Parents { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Child>()
            .HasMany(x => x.Parents)
            .WithMany(x => x.Children)
            .Map(c =>
            {
                c.MapLeftKey("ChildId");
                c.MapRightKey("ParentId");
                c.ToTable("ChildToParentMapping"); 
            });

    }
}

然后我将 OnModelCreating 更改为:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Child>()
            .HasMany(x => x.Parents)
            .WithMany(x => x.Children)
            .Map(c =>
            {
                c.MapLeftKey("ChildId");
                c.MapRightKey("ParentId");
                c.ToTable("ChildToParentMapping"); 
            });

        modelBuilder.Entity<Parent>()
           .HasMany(x => x.Children)
           .WithMany(x => x.Parents)
           .Map(c =>
           {
               c.MapLeftKey("ParentId");
               c.MapRightKey("ChildId");
               c.ToTable("ChildToParentMapping");
           });
    }

我发现和怀疑的是,第一次运行会生成这个 sql:

exec sp_executesql N'insert [dbo].[ChildToParentMapping]([ChildId], [ParentId])
values (@0, @1)
',N'@0 int,@1 int',@0=1,@1=2

与生成的第二个对比:

exec sp_executesql N'insert [dbo].[ChildToParentMapping]([ParentId], [ChildId])
values (@0, @1)
',N'@0 int,@1 int',@0=1,@1=2

你看到值翻转了吗?这里它实际上将 ChildId 列计为 ParentId。现在这对我来说不会崩溃,但我让 EF 创建数据库,这意味着它可能只是切换列名,如果我查看外键,它们也会被切换。如果您手动创建数据库,则情况可能并非如此。

简而言之:您的映射不相等,我希望使用其中之一,而那个可能是错误的。在较早的版本中,我猜 EF 以不同的顺序拾取它们。

更新: 对外键有点好奇,查了一下sql。

从第一个代码开始:

ALTER TABLE [dbo].[ChildToParentMapping] ADD CONSTRAINT [FK_dbo.ChildToParentMapping_dbo.Children_ChildId] FOREIGN KEY ([ChildId]) REFERENCES [dbo].[Children] ([ChildId]) ON DELETE CASCADE

从第二个代码开始:

ALTER TABLE [dbo].[ChildToParentMapping] ADD CONSTRAINT [FK_dbo.ChildToParentMapping_dbo.Children_ParentId] FOREIGN KEY ([ParentId]) REFERENCES [dbo].[Children] ([ChildId]) ON DELETE CASCADE

现在这不是很好。 ParentId 映射到 Children 肯定不是我们想要的。

那么第二个映射是不是错了?不是真的,因为看看我删除第一个时发生了什么:

ALTER TABLE [dbo].[ChildToParentMapping] ADD CONSTRAINT [FK_dbo.ChildToParentMapping_dbo.Parents_ParentId] FOREIGN KEY ([ParentId]) REFERENCES [dbo].[Parents] ([ParentId]) ON DELETE CASCADE

不知何故,有两个映射似乎把事情搞砸了。我不知道有没有错误。

关于c# - Entity Framework 5 升级后多对多关系左右键翻转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12192679/

有关c# - Entity Framework 5 升级后多对多关系左右键翻转的更多相关文章

  1. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  3. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  6. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  7. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

    我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

  10. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

随机推荐