Entity Framework Tutorial Basics(27):Update Entity Graph
Update Entity Graph using DbContext:
Updating an entity graph in disconnected scenario is a complex task. It is easy to add a new entity graph in disconnected mode, but to update an entity graph needs careful design consideration.
The problem in updating an entity graph in the disconnected scenario, is that the context doesn't know what operation was performed on it at the client side. As per the following figure, the new context doesn't know the state of each entity:
We need to identify the states of each entity in the entity graph, before calling the SaveChages() method of context. There are different patterns to identify entity state, which we need to consider in designing data layer with Entity Framework.
Patterns of Identifying Entity State in disconnected scenario:
There are several ways (some shown below) to identify an entity state in disconnected scenario:
- Using PrimaryKey (Id) property of an entity
- Having state property in entity set
Note: You can create your own design to identify an entity state based on your architecture. This is just for learning purposes.
1) Using PrimaryKey property of an entity:
You can use the PrimaryKey (Id) property of each entity to determine its entity state. However, you have to decide which of the following architectural rule to use:
- Each type of entity must have Id property (PK)
- Default value of Id property should be 0
As you can see in the figure shown above, the client fetches the Standard and Teacher entity graph and does some operations on it and then sends it to Context 2 to save the changes.
In the disconnected scenario, context2 doesn't know the state of each entity. It has to determine the state of the Standard entity by using StandardId and the state of the Teacher entity by using TeacherId property. If StandardId and TeacherID value is zero, that means it is a new entity and if it is not zero then it is a modified entity.
In the above figure, Standard, Teacher 1, and Teacher 2 have a non-zero Id property value so they are marked as Modified and Teacher 3 Id is zero so it is marked as Added.
The code snippet shown below uses Id property to mark an entity state:
Standard disconnectedStandard = null; using (var context = new SchoolDBEntities())
{
context.Configuration.ProxyCreationEnabled = false; disconnectedStandard = context.Standards.Where(s => s.StandardId == ).Include(s => s.Teachers).FirstOrDefault<Standard>();
}
//Update Standard in disconnected mode
disconnectedStandard.StandardName = "Edited Standard Name"; //Update teachers collection by editing first teacher and adding new teacher
disconnectedStandard.Teachers.ElementAt().TeacherName = "Edited Teacher Name";
disconnectedStandard.Teachers.Add(new Teacher() { TeacherName = "New Teacher", StandardId = disconnectedStandard.StandardId }); using (var newContext = new SchoolDBEntities())
{
//mark standard based on StandardId
newContext.Entry(disconnectedStandard).State = disconnectedStandard.StandardId == ? EntityState.Added : EntityState.Modified; //mark teacher based on StandardId
foreach (Teacher tchr in disconnectedStandard.Teachers)
newContext.Entry(tchr).State = tchr.TeacherId == ? EntityState.Added : EntityState.Modified; newContext.SaveChanges();
}
Advantages:
- No need for extra coding/processing to determine entity state.
- Good performance.
Disadvantages:
- Every entity type needs to have an Id property. It cannot determine states of an entity that do not have Id property.
- Cannot identify an Unchanged entity. It is set to Modified state even if the entity is not changed at all. So, there is an unnecessary database update statement for an unchanged entity.
- Cannot handle delete entity scenario. It needs to handle deletion separately.
2) Having State property in every entity:
Another way to determine entity state is to have a State property in every entity type and set an appropriate state from the client side in disconnected mode. Then we just need to set the entity state as the state property of an entity object before calling SaveChanges of the new context.
Example:
First of all, create an IEntityState interface with enum property called ObjectState:
interface IEntityObjectState
{
EntityObjectState ObjectState { get; set; }
} public enum EntityObjectState
{
Added,
Modified,
Deleted,
Unchanged
}
Now, implement an IEntityObjectState in each entity class, e.g. Standard and Teacher entity, as shown below:
public partial class Standard:IEntityObjectState
{
public Standard()
{
this.Students = new HashSet<Student>();
this.Teachers = new HashSet<Teacher>();
} public int StandardId { get; set; }
public string StandardName { get; set; }
public string Description { get; set; } public virtual ICollection<Student> Students { get; set; }
public virtual ICollection<Teacher> Teachers { get; set; }
[NotMapped]
public EntityObjectState ObjectState
{
get;
set;
}
} public partial class Teacher:IEntityObjectState
{
public Teacher()
{
this.Courses = new HashSet<Course>();
} public int TeacherId { get; set; }
public string TeacherName { get; set; }
public Nullable<int> StandardId { get; set; } public virtual ICollection<Course> Courses { get; set; }
public virtual Standard Standard { get; set; } [NotMapped]
public EntityObjectState ObjectState
{
get;
set;
} }
Set the appropriate state in disconnected mode on client side:
Teacher existingTeacher = null; using (var context = new SchoolDBEntities())
{
context.Configuration.ProxyCreationEnabled = false;
existingTeacher = context.Teachers.FirstOrDefault<Teacher>(); }
Standard disconnectedStandard = new Standard() { StandardName = "New Standard", ObjectState = EntityObjectState.Added };
existingTeacher.ObjectState = EntityObjectState.Modified;
//add existing teacher(in db) to standard
disconnectedStandard.Teachers.Add(existingTeacher);
//add new standard
disconnectedStandard.Teachers.Add(new Teacher() { TeacherName = "New teacher", StandardId = disconnectedStandard.StandardId, ObjectState = EntityObjectState.Added });
Set the entity state as per ObjectState before calling SaveChanges.
using (var newContext = new SchoolDBEntities())
{
//check the ObjectState property and mark appropriate EntityState
if (disconnectedStandard.ObjectState == EntityObjectState.Added)
newContext.Entry(disconnectedStandard).State = System.Data.Entity.EntityState.Added;
else if (disconnectedStandard.ObjectState == EntityObjectState.Modified)
newContext.Entry(disconnectedStandard).State =System.Data.Entity.EntityState.Modified;
else if (disconnectedStandard.ObjectState == EntityObjectState.Deleted)
newContext.Entry(disconnectedStandard).State = System.Data.Entity.EntityState.Deleted;
else
newContext.Entry(disconnectedStandard).State = System.Data.Entity.EntityState.Unchanged; //check the ObjectState property of each teacher and mark appropriate EntityState
foreach (Teacher tchr in disconnectedStandard.Teachers)
{
if (tchr.ObjectState == EntityObjectState.Added)
newContext.Entry(tchr).State = System.Data.Entity.EntityState.Added;
else if (tchr.ObjectState == EntityObjectState.Modified)
newContext.Entry(tchr).State = System.Data.Entity.EntityState.Modified;
else if (tchr.ObjectState == EntityObjectState.Deleted)
newContext.Entry(tchr).State = System.Data.Entity.EntityState.Deleted;
else
newContext.Entry(tchr).State = System.Data.Entity.EntityState.Unchanged;
}
//save changes
newContext.SaveChanges();
}
Advantages:
- No need for extra coding/processing to determine the entity state
- Handles Added, Modified, Deleted, and Unchanged states properly
- No unnecessary update call for unchanged entities.
Disadvantage:
- Need to set the appropriate states of each entity in disconnected mode. So there is a need to be extra careful in disconnected mode.
Entity Framework Tutorial Basics(27):Update Entity Graph的更多相关文章
- Entity Framework Tutorial Basics(4):Setup Entity Framework Environment
Setup Entity Framework Environment: Entity Framework 5.0 API was distributed in two places, in NuGet ...
- Entity Framework Tutorial Basics(42):Colored Entity
Colored Entity in Entity Framework 5.0 You can change the color of an entity in the designer so that ...
- Entity Framework Tutorial Basics(5):Create Entity Data Model
Create Entity Data Model: Here, we are going to create an Entity Data Model (EDM) for SchoolDB datab ...
- Entity Framework Tutorial Basics(26):Add Entity Graph
Add Entity Graph using DbContext: Adding entity graph with all new entities is a simple task. We can ...
- Entity Framework Tutorial Basics(24):Update Single Entity
Update Existing Entity using DBContext in Disconnected Scenario: In this chapter, you will learn how ...
- Entity Framework Tutorial Basics(40):Validate Entity
Validate Entity You can write custom server side validation for any entity. To accomplish this, over ...
- Entity Framework Tutorial Basics(1):Introduction
以下系列文章为Entity Framework Turial Basics系列 http://www.entityframeworktutorial.net/EntityFramework5/enti ...
- Entity Framework Tutorial Basics(32):Enum Support
Enum in Entity Framework: You can now have an Enum in Entity Framework 5.0 onwards. EF 5 should targ ...
- Entity Framework Tutorial Basics(31):Migration from EF 4.X
Migration from Entity Framework 4.1/4.3 to Entity Framework 5.0/6.0 To migrate your existing Entity ...
随机推荐
- vs2012 sln和.vcxproj有什么区别
sln是解决方案的配置,主要是管理这个方案里的多个vcxprojvcxproj是工程的配置文件,管理工程中细节比如包含的文件,引用库等一般没有sln,也可以直接打开vcxproj,也可以重新生成sln ...
- BZOJ- 2733: 永无乡 (并查集&线段树合并)
题意:给定N个节点,K次操作,操作有两种,1是合并两个集合,2是求某个集合的第K大(从小到大排序). 思路:合并只要启发式即可.此题可以用线段树,保存1到N的排序的出现次数和. 复杂度O(NlogN) ...
- LeetCode Shortest Unsorted Continuous Subarray
原题链接在这里:https://leetcode.com/problems/shortest-unsorted-continuous-subarray/description/ 题目: Given a ...
- [转]JavaScript之数据类型
数据类型 JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String.还有1种复杂数据类型——Object,Object本 ...
- 极路由U-boot解锁刷root固件教程,root后可刷华硕、如意云等多种固件,附赠全套刷软
9008正式版固件将会封堵此漏洞,想root的同学尽快了.安装新工具箱里的root保留,可升级官方最新固件并保留root. 此方法并非本人原创,只是将root的过程和经验做个总结,比较适合菜鸟做参考, ...
- 静默安装Azure CLI
Azure的CLI目前已经是基于Python的2.0版本.其信息在下面的链接可以找到: https://github.com/Azure/azure-cli 其安装方法可以根据网站上描述的命令实现: ...
- 蓝桥杯 算法训练 ALGO-119 寂寞的数
算法训练 寂寞的数 时间限制:1.0s 内存限制:256.0MB 问题描述 道德经曰:一生二,二生三,三生万物. 对于任意正整数n,我们定义d(n)的值为为n加上组成n的各个数字的和.例如,d(2 ...
- 机器学习:调整kNN的超参数
一.评测标准 模型的测评标准:分类的准确度(accuracy): 预测准确度 = 预测成功的样本个数/预测数据集样本总数: 二.超参数 超参数:运行机器学习算法前需要指定的参数: kNN算法中的超参数 ...
- Regexp:目录
ylbtech-Regexp:目录 1.返回顶部 1. http://www.runoob.com/regexp/regexp-tutorial.html 2. 2.返回顶部 3.返回顶部 4 ...
- c# linq查询语句详细使用介绍
本文介绍Linq的使用方法 linq介绍 LINQ只不过是实现IEnumerable和IQueryable接口的类的扩展方法的集合. LINQ可以查询IEnumerable集合或者IQueryable ...