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 ...
随机推荐
- orderby与groupby同时使用
两个同时使用:要求排序其他字段 select c1,max(c2) as a from table group by c1 order by a; in查询按照排序结果: ,,,....)
- 解决Openwrt安装插件提示一下错误的办法
解决Openwrt安装插件提示一下错误的办法 Openwrt安装17ce插件,提示一下错误: Collected errors: * check_data_file_clashes: Package ...
- PHP打印日期
<?php header("content-type:text/html;charset=utf-8"); echo "今天是 " . date(&quo ...
- js数组详解
1,什么是数组 数组是值得有序集合,每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引.js的数组是无类型的,数组元素可以是任意类型,同一个数组中的不同元素可能是对象或数组 ...
- 删除SVN版本信息 .svn文件夹
环境:MyEclipse.Windows 问题描述: 在MyEclipse中当我们需要将一个文件夹(包含若干文件或嵌套文件夹)拷贝到另一个文件夹时,此时文件内容虽然拷贝过去了,但其下面的 .svn文件 ...
- 【Python】list和tuple 区别比较
列表 List classmates = ['Michael', 'Bob', 'Tracy'] 元组 Tuple tuple一旦初始化就不能修改,比如同样是列出同学的名字: >>> ...
- c++ 读写结构体到文件
可以使用fwrite()将一个结构体写入文件: fwrite(&some_struct,sizeof somestruct,1,fp);对应的fread函数可以再把它读出来,此处fwrite ...
- 《effective c++》读书笔记(上)
最近在读<Effective C++>,确实是经典之作,但是有的条款也需要一些细节补充,所以都列在这篇文章里,希望能不断更新,个人阅读的是第三版,不包括C++ 11的内容. 条款1:视C+ ...
- lsqnonlin函数使用方法
非线性最小二乘函数 lsqnonlin 格式x = lsqnonlin(fun,x0) %x0 为初始解向量:fun为,i=1,2,-,m,fun返回向量值F,而不是平方和值,平方和隐含在方法中, ...
- java通过jxls框架实现导入导出excel
//使用jxls报表生成工具,把java实体类导出生成 Excel文件或导入 Excel 插入数据库 02 03//读取04 05public class ReadExcel {06 private ...