Many-to-many relationships in EF Core 2.0 – Part 4: A more general abstraction
In the last few posts we saw how to hide use of the join entity from two entities with a many-to-many relationship. This post doesn’t add any additional functionality, it just abstracts some of what we saw so it can be re-used more easily.
To start with we define an interface for join entities:
public interface IJoinEntity<TEntity>
{
TEntity Navigation { get; set; }
}
Any join entity will implement this interface twice; once for each side:
public class PostTag : IJoinEntity<Post>, IJoinEntity<Tag>
{
public int PostId { get; set; }
public Post Post { get; set; }
Post IJoinEntity<Post>.Navigation
{
get => Post;
set => Post = value;
} public int TagId { get; set; }
public Tag Tag { get; set; }
Tag IJoinEntity<Tag>.Navigation
{
get => Tag;
set => Tag = value;
}
}
We can now re-write our facade colection to use any types that implement this interface:
public class JoinCollectionFacade<TEntity, TOtherEntity, TJoinEntity>
: ICollection<TEntity>
where TJoinEntity : IJoinEntity<TEntity>, IJoinEntity<TOtherEntity>, new()
{
private readonly TOtherEntity _ownerEntity;
private readonly ICollection<TJoinEntity> _collection; public JoinCollectionFacade(
TOtherEntity ownerEntity,
ICollection<TJoinEntity> collection)
{
_ownerEntity = ownerEntity;
_collection = collection;
} public IEnumerator<TEntity> GetEnumerator()
=> _collection.Select(e => ((IJoinEntity<TEntity>)e).Navigation).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator(); public void Add(TEntity item)
{
var entity = new TJoinEntity();
((IJoinEntity<TEntity>)entity).Navigation = item;
((IJoinEntity<TOtherEntity>)entity).Navigation = _ownerEntity;
_collection.Add(entity);
} public void Clear()
=> _collection.Clear(); public bool Contains(TEntity item)
=> _collection.Any(e => Equals(item, e)); public void CopyTo(TEntity[] array, int arrayIndex)
=> this.ToList().CopyTo(array, arrayIndex); public bool Remove(TEntity item)
=> _collection.Remove(
_collection.FirstOrDefault(e => Equals(item, e))); public int Count
=> _collection.Count; public bool IsReadOnly
=> _collection.IsReadOnly; private static bool Equals(TEntity item, TJoinEntity e)
=> Equals(((IJoinEntity<TEntity>)e).Navigation, item);
}
The main advantage of this new abstraction is that specific delegates to select target entities and create join entities are not needed anymore. So now in our entities we can create collections like so:
public class Post
{
public Post() => Tags = new JoinCollectionFacade<Tag, Post, PostTag>(this, PostTags); public int PostId { get; set; }
public string Title { get; set; } private ICollection<PostTag> PostTags { get; } = new List<PostTag>(); [NotMapped]
public ICollection<Tag> Tags { get; }
} public class Tag
{
public Tag() => Posts = new JoinCollectionFacade<Post, Tag, PostTag>(this, PostTags); public int TagId { get; set; }
public string Text { get; set; } private ICollection<PostTag> PostTags { get; } = new List<PostTag>(); [NotMapped]
public IEnumerable<Post> Posts { get; }
}
Everything else, including the little test application, is unchanged from the previous post.
Many-to-many relationships in EF Core 2.0 – Part 4: A more general abstraction的更多相关文章
- Many-to-many relationships in EF Core 2.0 – Part 1: The basics
转载这个系列的文章,主要是因为EF Core 2.0在映射数据库的多对多关系时,并不像老的EntityFramework那样有原生的方法进行支持,希望微软在以后EF Core的版本中加入原生支持多对多 ...
- Many-to-many relationships in EF Core 2.0 – Part 2: Hiding as IEnumerable
In the previous post we looked at how many-to-many relationships can be mapped using a join entity. ...
- Many-to-many relationships in EF Core 2.0 – Part 3: Hiding as ICollection
In the previous post we ended up with entities that hide the join entity from the public surface. Ho ...
- EF Core 1.0 和 SQLServer 2008 分页的问题
EF Core 1.0 在sqlserver2008分页的时候需要指定用数字分页. EF Core1.0 生成的分页语句中使用了 Featch Next.这个语句只有在SqlServer2012的时候 ...
- ASP.NET Core 开发-Entity Framework (EF) Core 1.0 Database First
ASP.NET Core 开发-Entity Framework Core 1.0 Database First,ASP.NET Core 1.0 EF Core操作数据库. Entity Frame ...
- EF Core 1.0中使用Include的小技巧
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:由于EF Core暂时不支持Lazy Loading,所以利用Include来加载额外 ...
- .NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0简介
.NET Core 1.0.ASP.NET Core 1.0和EF Core 1.0简介 英文原文:Reintroducing .NET Core 1.0, ASP.NET Core 1.0, and ...
- EF Core 2.0 新特性
前言 目前 EF Core 的最新版本为 2.0.0-priview1-final,所以本篇文章主要是针对此版本的一些说明. 注意:如果你要在Visual Studio 中使用 .NET Core 2 ...
- EF Core 2.0使用MsSql/Mysql实现DB First和Code First
参考地址 EF官网 ASP.NET Core MVC 和 EF Core - 教程系列 环境 Visual Studio 2017 最新版本的.NET Core 2.0 SDK 最新版本的 Windo ...
随机推荐
- clean code 第一章笔记
我们都曾有过这样的经历:自己写的烂程序竟然可以运行,然后就认为能运行的烂代码总比什么都没有强.还会有这样的想法:总有一天我会修改它.但是,LeBlanc(勒布朗)法则表示:稍后等于永不(Later e ...
- csharp: Getting all image files in folder
/// <summary> /// /// </summary> /// <param name="sender"></param> ...
- Angularjs ngTable使用备忘
项目中用到angularjs的表格ng-table,功能相当强大,像搜索.排序.checkbox.分页.每页表格显示数目等都有.API,demo什么的也只能参考官网了.这里做个备忘,哪天肯定还会用到. ...
- SpringCloud+Git+Maven+Docker+Jenkins自动化构建
1.JDK安装-OpenJDK安装 yum list java-1.8* yum install -y java-1.8.0-openjdk-devel.x86_64 PS: JDK安装有两种方法:一 ...
- RocketMQ读书笔记2——生产者
[生产者的不同写入策略] 生产者向消息队列里写入数据,不同的业务需要生产者采用不同的写入策略: 同步发送.异步发送.延迟发送.发送事务消息等. [DefaultMQProduce示例] public ...
- eclipse 出现 jar包找不到 问题记录
同事在下载maven私服项目的时候,自动更新失败.maven 一直提示 parent 更新失败但是其他的项目都是正常的,这就奇怪了. 最后 仔细查询后,发现是 同事在下载项目时候,项目是分clien ...
- 【PHP系列】框架的抉择
缘起 在PHP开发中,选择合适的框架有助于加快软件开发,节约宝贵的项目时间,让开发者专注于功能的实现上.框架的问题是需要很多的投入,选择框架时,我们更看重这个框架的未来,存在多年的大型框架必须要有好的 ...
- 【Leetcode】【Medium】Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...
- Session跨域、Session共享、Mode=StateSever方式解决问题
前言 很多童鞋在工作或面试的过程中,也许会遇到这样的问题,使用Session,怎样让多个站点实现Session共享的问题,也就是在A站点登录,那么在B站点就不需要重新登录了那?如果采用Session保 ...
- 安装python File "/usr/bin/pip", line 11, in <module> sys.exit(main()) File "/usr/lib/python3.4/site-packages/pip/__init__.py", line 215, in main locale.setlocale(locale.LC_ALL, '') File "/u
$ uname -a Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1+deb8u6 (2015-11-09) x86_64 GNU ...