Entity Framework 最佳实践
2020-07-08

平时如果需要搭建原型,选择 Entity Framework(后简称 EF)将会帮助您更快地交付和迭代

但是,EF 虽好,可不要贪杯哦。原型阶段使用 EF 完全莫得问题,但是到后期项目变的越来越大,需要真正交付产品时,建议还是切换到其他的 ORM 框架或者 ADO.NET,因为,这里面真的有很多莫名坑,新手,甚至是有一定经验的程序员都会不知不觉地踩进去。

EF 访问数据的架构

EF 其实就是负责 C# Object 和数据库数据之间的映射,让 .Net 开发人员操作 Object 就像操作数据库一样丝滑,背后 EF 会自动转换 sql 代码。

祭一张 EF 数据访问架构图

Entity Framework architecture for accessing data

来自 Microsoft Docs

下面就是我这个踩坑小能手用泪水和汗水总结的笔记,希望下次再用 EF 的时候,能够减少入坑次数。

及时调用 .ToList() 方法 !!!

这第一条,自然是有它的道理的。只怪自己当初没有好好理解透彻 EF 深层原理。

EF 默认会做很多操作,优化我们的查询,比如延迟发送请求,再比如合并查询请求。这就引进了一个常见的错误,

.ToList() 方法就是告诉立即执行查询,

序列化配置

把 Controller 返回结果序列化成 JSON 字符串时,在 Global.asax.cs 文件 Application_Start 方法中添加以下代码:

1
2
3
4
5
6
/// append below code to the end of Application_Start
var serializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
/// no returned loop reference objects
serializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
/// decrease json string length by removing null value
serializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;

API 仅返回页面需要的字段

好习惯!虽然累了点,但是优秀的程序员始终将高性能和可扩展性放在心里 🙂

查询表时,删除关联表结果

同上一点相关,当数据库的表有外键时,如果直接查询该表,它相关联表的记录也会跟着返回,不仅拖慢查询,序列化返回页面时也会徒增流量。解决办法是返回结果集前,把相应的属性置空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/// <summary>
/// the EF will return referencing tables along with current table value,
/// this method will prevent this default behavior
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <returns></returns>
public static IEnumerable<T> ReturnEFResult<T>(IEnumerable<T> data) where T : class, new()
{
if (IsNullOrEmptyList(data)) return data;
// remove all ICollection type fields
List<T> ls = new List<T>();
//Type icollectionType = typeof(ICollection<>);
//var props = typeof(T).GetProperties().Where(_ => !_.PropertyType.IsAssignableFrom(icollectionType));

var props = typeof(T).GetProperties().Where(_ =>
{
//return !ImplementsInterface(_.PropertyType, icollectionType);
var pt = _.PropertyType;
return pt.Name != "ICollection`1" && !pt.Namespace.StartsWith("your.namespace.here");
}).ToList();
foreach (T d in data)
{
T tmp = new T();
foreach (var p in props)
{
p.SetValue(tmp, p.GetValue(d));
}
ls.Add(tmp);
}
return ls;
}

新增、更新或删除记录,记得调用 SaveChanges() 方法提交改动

多撸几次自然就记住了,不浪费各自精力了。

(待续)

是的,因为懒,就到这里了,鸽了。。。

参考链接

本文链接:
content_copy https://zxs66.github.io/2020/07/08/best-practices-for-Entity-Framework/