Entity Framework 4.1+ 多对多关系更改跟踪

2024-04-28

如何检测 ICollection 属性的更改(多对多关系)?

public class Company
{
    ...

    public virtual ICollection<Employee> Employees { get; set; }
}

using (DataContext context = new DataContext(Properties.Settings.Default.ConnectionString))
{
    Company company = context.Companies.First();
    company.Employees.Add(context.Employees.First());

    context.SaveChanges();
}

public class DataContext : DbContext
{
    public override int SaveChanges()
    {
        return base.SaveChanges();

        // Company's entity state is "Unchanged" in this.ChangeTracker
    }
}

以下是如何查找所有已更改的多对多关系。我已将代码实现为扩展方法:

public static class IaExtensions
{
    public static IEnumerable<Tuple<object, object>> GetAddedRelationships(
        this DbContext context)
    {
        return GetRelationships(context, EntityState.Added, (e, i) => e.CurrentValues[i]);
    }

    public static IEnumerable<Tuple<object, object>> GetDeletedRelationships(
        this DbContext context)
    {
        return GetRelationships(context, EntityState.Deleted, (e, i) => e.OriginalValues[i]);
    }

    private static IEnumerable<Tuple<object, object>> GetRelationships(
        this DbContext context,
        EntityState relationshipState,
        Func<ObjectStateEntry, int, object> getValue)
    {
        context.ChangeTracker.DetectChanges();
        var objectContext = ((IObjectContextAdapter)context).ObjectContext;

        return objectContext
            .ObjectStateManager
            .GetObjectStateEntries(relationshipState)
            .Where(e => e.IsRelationship)
            .Select(
                e => Tuple.Create(
                    objectContext.GetObjectByKey((EntityKey)getValue(e, 0)),
                    objectContext.GetObjectByKey((EntityKey)getValue(e, 1))));
    }
}

一些解释。多对多关系在 EF 中表示为独立关联 (IA)。这是因为关系的外键没有在对象模型中的任何地方公开。在数据库中,FK 位于连接表中,并且该连接表对对象模型是隐藏的。

IAs 在 EF 中使用“关系条目”进行跟踪。它们与从 DbContext.Entry 获取的 DbEntityEntry 对象类似,只不过它们表示两个实体之间的关系而不是实体本身。关系条目未在 DbContext API 中公开,因此您需要下拉至 ObjectContext 才能访问它们。

当两个实体之间创建新关系时,就会创建一个新关系条目,例如通过将 Employee 添加到 Company.Employees 集合。该关系处于已添加状态。

同样,当删除两个实体之间的关系时,关系条目将进入“已删除”状态。

这意味着要查找更改的多对多关系(或实际上任何更改的 IA),我们需要查找添加和删除的关系条目。这就是 GetAddedRelationships 和 GetDeletedRelationships 的作用。

一旦我们有了关系条目,我们就需要理解它们。为此,您需要了解一些内幕知识。已添加(或未更改)关系条目的 CurrentValues 属性包含两个值,它们是关系两端实体的 EntityKey 对象。同样,但令人烦恼的略有不同,已删除关系条目的 OriginalValues 属性包含已删除关系两端实体的 EntityKey 对象。

(是的,这太可怕了。请不要责怪我——这已经是我时代之前的事情了。)

CurrentValues/OriginalValues 的差异是我们将委托传递给 GetRelationships 私有方法的原因。

一旦我们有了 EntityKey 对象,我们就可以使用 GetObjectByKey 来获取实际的实体实例。我们将它们作为元组返回,然后您就得到了它。

这里有一些实体、上下文和初始化器,我用来测试它。 (注意——测试并不广泛。)

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Employee> Employees { get; set; }

    public override string ToString()
    {
        return "Company " + Name;
    }
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Company> Companies { get; set; }

    public override string ToString()
    {
        return "Employee " + Name;
    }
}

public class DataContext : DbContext
{
    static DataContext()
    {
        Database.SetInitializer(new DataContextInitializer());
    }

    public DbSet<Company> Companies { get; set; }
    public DbSet<Employee> Employees { get; set; }

    public override int SaveChanges()
    {
        foreach (var relationship in this.GetAddedRelationships())
        {
            Console.WriteLine(
                "Relationship added between {0} and {1}",
                relationship.Item1,
                relationship.Item2);
        }

        foreach (var relationship in this.GetDeletedRelationships())
        {
            Console.WriteLine(
                "Relationship removed between {0} and {1}",
                relationship.Item1,
                relationship.Item2);
        }

        return base.SaveChanges();
    }

}

public class DataContextInitializer : DropCreateDatabaseAlways<DataContext>
{
    protected override void Seed(DataContext context)
    {
        var newMonics = new Company { Name = "NewMonics", Employees = new List<Employee>() };
        var microsoft = new Company { Name = "Microsoft", Employees = new List<Employee>() };

        var jim = new Employee { Name = "Jim" };
        var arthur = new Employee { Name = "Arthur" };
        var rowan = new Employee { Name = "Rowan" };

        newMonics.Employees.Add(jim);
        newMonics.Employees.Add(arthur);
        microsoft.Employees.Add(arthur);
        microsoft.Employees.Add(rowan);

        context.Companies.Add(newMonics);
        context.Companies.Add(microsoft);
    }
}

这是使用它的示例:

using (var context = new DataContext())
{
    var microsoft = context.Companies.Single(c => c.Name == "Microsoft");
    microsoft.Employees.Add(context.Employees.Single(e => e.Name == "Jim"));

    var newMonics = context.Companies.Single(c => c.Name == "NewMonics");
    newMonics.Employees.Remove(context.Employees.Single(e => e.Name == "Arthur"));

    context.SaveChanges();
} 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Entity Framework 4.1+ 多对多关系更改跟踪 的相关文章

  • 如何简单地添加指向 Spring Data REST 实体的链接

    我有带有 Spring Data JPA 的实体 但为了生成有关它们的统计信息 我在 Spring 中使用 jOOQ Repository 由于我的方法返回一个List的实体 或Double 我如何将它们公开为链接 假设我有一个User实体
  • 实体框架在不同的工作站上生成不同的查询

    我们在单个开发人员机器和一些客户端上遇到问题 单个 Linq 查询 生成两个不同的 SQL 查询 问题实际上是第二个查询有 firebird 不支持的 OUTER APPLY 语句 我们认为这不是代码问题 而是环境问题 但我会粘贴代码 li
  • 当 edmx 文件位于单独的项目中时出错

    我有问题说 在配置中找不到指定的命名连接 或者不打算与EntityClient提供者 或无效 我的 edmx 文件位于单独的项目中 但该项目的连接字符串app config 什么可能导致问题 确保 app config 位于设置为启动项目的
  • EF Core - 在运行时向数据库添加新表

    我有一个 asp net core 项目 需要能够在运行时支持插件 因此 我需要根据插入的内容生成数据库表 每个插件都分为单独的项目 并且它们具有他们自己的 DbContext 类 要使用的插件在编译时是未知的 只有在运行时才知道 现在在
  • 使用 linq 2 实体检查 where 子句的两个条件

    嗨 我有一个名为 产品 的表 其中包含列 product id prodcut name prodcut price values like 1200 2000 3000 100 prodcut desc category id 1 2 3
  • 在 Grails 域对象中维护自引用多对多关系的双方

    我在让多对多关系在 grails 中工作时遇到一些问题 以下内容是否有明显错误 class Person static hasMany friends Person static mappedBy friends friends Strin
  • 应用程序内的 SQLite 文件版本兼容性

    我有一个 C NET 应用程序 一种复杂的计算应用程序 其中用户输入数据 处理后的信息使用 JSON 序列化和 EF 保存到 SQLite 文件中 需要时可以将其加载到我们的应用程序中 应用程序在开发过程中经历了很多变化 类也被修改 因此
  • 将大量实体插入 SQL Server 2012 [重复]

    这个问题在这里已经有答案了 我正在进行一个使用 Entity Framework 5 和 SQL Server 2012 的项目 我们需要一次插入大量行 100k 个实体的顺序 基本上 我们有一个物理程序 它输出大量二进制数据 然后我们需要
  • WinForms 中的 EF:如何过滤 BindingSource/DGW 中的数据 (.Local.ToBindingList())

    我按照本教程生成了 EF 模型 首先是数据库 和数据源http msdn microsoft com en us data jj682076 aspx http msdn microsoft com en us data jj682076
  • 使用实体框架重叠约会

    我将 asp net mvc 与实体框架一起使用 我有一个包含 startat 字段 endat 字段和 roomid 字段 称为 SpaceConfigurationId 的约会列表 并且希望查找给定房间已重复预订的约会列表 可以假设 e
  • 如何使用 Entity Framework Code First 在两个实体之间建立多个一对多关系

    下面是保存关系数据库记录的简单方法 该方法运行得很好 我对一种情况有疑问 在此之前 我需要知道如果数据库复杂性增加 我所采用的方法会遇到什么困难 还有更好 高效但简单的方法吗 一对一 tb student store student det
  • 不支持 EF6 上下文类型“System.Data.Entity.Core.Objects.ObjectContext”

    我有一个使用 Visual Studio 2013 和 ADO NET 实体数据模型 EF6 创建的新项目 现在我必须使用一些动态数据函数 例如访问 MetaTable 对象 所以我添加以下代码 MetaModel model new Me
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • SQLAlchemy 通过关联对象声明式多对多自连接

    我有一个用户表和一个朋友表 它将用户映射到其他用户 因为每个用户可以有很多朋友 这个关系显然是对称的 如果用户A是用户B的朋友 那么用户B也是用户A的朋友 我只存储这个关系一次 除了两个用户 ID 之外 Friends 表还有其他字段 因此
  • EF4如何在多对多关系中公开联接表

    假设我有以下表格 Essence EssenceSet 和 Essence2EssenceSet 其中 Essence2EssenceSet 仅保存前 2 个表的 ID 以形成 M M 关系 在 EF 中 由于 Essence2Essenc
  • 实体框架 - 相关的 ICollection 被具体化为 HashSet

    我在我的项目中使用实体框架 POCO 代理 延迟加载 今天我很惊讶地看到这个班级Transaction有其相关合集Rows物化为HashSet 代替EntityCollection 我需要EntityCollection用于跟踪集合中的更改
  • 构建视图模型的最佳方法是什么?

    我正在使用带有实体框架的 asp net mvc 并开始学习 DDD 我正在从事包含调查的项目 这是我的域模型 public class Survey public int SurveyID get set public string Na
  • 如何在实体框架中完全锁定一行

    我正在处理的情况是我们正在处理金钱交易 例如 我有一个用户钱包表 其余额位于该行 UserId Wallet Id Balance 现在 在我们的网站和网络服务中 每次发生特定交易时 我们都需要 检查是否有足够的资金可用于执行该交易 从余额
  • 包管理器控制台中缺少文件错误

    我们的开发团队的一些成员在打开包管理器控制台时开始看到以下错误 它完全阻止我们运行实体框架命令 我们已经检查过并且提到的文件确实存在 GetEvent types ps1xml Diagnostics Format ps1xml Diagn
  • 哪一条路?数据库优先、模型优先、仅代码?

    最近我通过Pro Entity Framework 4 0这本书学习了Entity Framework 现在 我想用EF来写项目 有了这些条件 哪种方式更好更灵活 我的观点是模型优先 但我想知道你的意见 thanks 读这个 EF 4 1

随机推荐

  • jnius 1.1导入错误

    当我想导入 jnius 时出现如下错误 Traceback most recent call last File C Python27 lib site packages jnius init py line 12 in
  • 使用 oauth azure 数据工厂进行分页

    在 Azure 数据工厂内 我通过 REST 复制活动调用 microsoft graph 利用 REST 来获取服务的访问令牌 Graph api 最多返回 200 个结果 因此我有兴趣使用可以在源中创建的分页规则 在邮递员中我可以看到我
  • window.location 的 .NET MVC jQuery 相对路径

    我有一个非常简单的问题 但似乎无法弄清楚 由于 MVC 构建 URL 的方式 它包括所有路由信息 以下内容不起作用 我希望路径名仅返回虚拟目录路径 我所做的只是当用户从下拉列表中选择 ID 时重定向到不同的路由 document ready
  • axios 拦截器内的 useContext

    我不明白为什么我的 useContext 没有在这个函数中被调用 import useContext from react import MyContext from contexts MyContext js import axios f
  • 使用 Node.js 就地流式传输和转换文件

    我想做这样的事情 var fs require fs var through require through var file path to file json var input fs createReadStream file utf
  • 如何将行为设置为投票而不需要用户登录?

    我试图允许用户无需登录 注册即可对线程进行投票 以提高用户参与度 我该怎么做呢 目前 我当前的流程是将投票与访问者的 IP 地址联系起来 以防止多次投票 但另一个问题是 request remote ip 没有为我提供正确的 IP 我在学校
  • 我如何获得 github actions runner 令牌

    我想在工作流程中创建一个虚拟机并设置为自托管运行程序 目前 阻碍我的是缺乏为我提供 Runner Token 的 API 如果存在 我可以创建该实例并将其注册为运行程序 以便能够在下一个作业中使用它 现在有人有办法获得跑步者令牌吗 延迟更新
  • JTable 如何在行之间添加行

    我之前一直在寻找这个问题很长一段时间 但我找不到任何关于这个问题或主题的问题 我假设这可能是不可能做到的 尽管这看起来很奇怪 因为该功能很有用 我希望在有 3 行的情况下 不是在末尾添加另一行 而是在第 1 行之后添加 这有可能吗 请不要提
  • BigQuery 中的 EXP() 返回浮点错误

    我有以下查询 SELECT EXP col FROM project dataset tablename Where col is FLOAT 但是 我收到此错误 Error Floating point error in function
  • sizeof() 函数如何用于 C 中的结构?

    结构体定义如下 typedef struct Sample int test char strtest Sample 在Main Function中 我将结构体称为Sizeof sizeof struct Sample 我听说结构体上 si
  • 如何制作包含DLL文件的JAR文件?

    我购买了一个第三方Java库 其中包括一个JAR文件和两个DLL文件 我编写了自己的 Java 程序来调用第三方 JAR 文件 现在我的问题是如何将我的所有代码打包到一个 JAR 文件中 其中包含我的所有代码以及第三方 JAR 和 DLL
  • 使用 AffineTransform 将形状缩放/转换为给定矩形

    我正在尝试缩放 翻译 java awt Shape with 仿射变换为了将其绘制在定义的边界矩形中 此外 我想在具有 的绘图区域中绘制它zoom 范围 我尝试了 AffineTransform 的各种串联 但找不到正确的序列 例如 以下解
  • 在没有 Webpack 的情况下使用模块“child_process”

    我正在使用 Webpack 来捆绑依赖项 其中之一是电子邮件服务postmark 该服务依赖于称为child process显然是随节点一起提供的 问题是 当我尝试运行 webpack 来捆绑我的应用程序时 它会抱怨 找不到模块 错误 无法
  • 为什么使用 System.Threading.Interlocked.Decrement 而不是减号?

    我将一些 C 代码转换为 vb net converter telerik com 将其转换为 i 进入这个 System Math Max System Threading Interlocked Decrement i i 1 所有的花
  • 我可以在 React Native 中需要一个专门用于 iOS 的模块吗?

    我目前正在使用react native safari view https github com naoufal react native safari view我的 React Native 项目中用于在 iOS 中显示 Web 视图的模
  • 如何让一个不可见的透明按钮起作用?

    查看 Unity 论坛和问答网站中的一些答案 如何制作隐形按钮的答案不起作用 因为删除与按钮关联的图像会使其不起作用 如何解决这个问题并保持不可见属性 同时允许按钮实际工作 这是 Unity 的怪异之处之一 100 的现实世界项目都需要这个
  • 如何转换 R 中列匹配模式中的值

    我有这个数据框mydf 专栏nucleotide可以有A T G C字母 我想更改字母A to T C to G G to C and T to A 如果strand列是 我该怎么做 mydf lt structure list seqna
  • 使用详细信息和摘要标签作为可折叠内联元素

    我正在努力研究这个问题的解决方案 找到一种方法来实现可折叠按钮 或其他类似对象 这样 它们可以在同一行中使用 单击时 其内容显示在按钮所在行和下一行之间 他们反应敏捷 内容的样式独立于标题 我制作这个 gif 是为了更好地了解我想要获得什么
  • 使用 CSS 检查滚动

    我正在尝试创建一个纯 100 CSS 无 jQuery 返回顶部 按钮 但我希 望该按钮仅在访问者向下滚动页面时显示 是否可以用 CSS 来检查这一点 因此 如果访问者向下滚动一点 则会显示 返回顶部 按钮 Thanks 根据光标位置确定
  • Entity Framework 4.1+ 多对多关系更改跟踪

    如何检测 ICollection 属性的更改 多对多关系 public class Company public virtual ICollection