Entity Framework DbContext Change Tracker API

DbSet有一個Local,是用來存放從資料庫中取得的資料

namespace ConsoleApplication1
{
using ConsoleApplication1.Models;
using System;
using System.Data.Entity;

class Program
{
static void Main(string[] args)
{
// 初始化資料庫
Database.SetInitializer(new MyInit());
using (DemoContext db = new DemoContext())
{
db.Database.Initialize(false);
Console.WriteLine(db.Topic.Local.Count);
db.Topic.Load();
Console.WriteLine(db.Topic.Local.Count);
}
}
}
}


Local屬性是一個ObservableCollection,可以透過CollectionChanged事件來得到Local集合中發生變化的通知
namespace ConsoleApplication1
{
using ConsoleApplication1.Models;
using System;
using System.Data.Entity;

class Program
{
static void Main(string[] args)
{
// 初始化資料庫
Database.SetInitializer(new MyInit());
using (DemoContext db = new DemoContext())
{
db.Database.Initialize(false);

db.Topic.Local.CollectionChanged += (s, a) =>
{
if (a.NewItems != null)
{
foreach (Topic item in a.NewItems)
{
Console.WriteLine(“Added:” + item.TopicTitle);
}
}

if (a.OldItems != null)
{
foreach (Topic item in a.OldItems)
{
Console.WriteLine(“Removed:” + item.TopicTitle);
}
}
};

Topic topic = new Topic { TopicTitle = “abc” };
db.Topic.Add(topic);
db.Topic.Remove(topic);
}
}
}
}


當資料取出到DbContext之後,接下來的資料異動會透過EntityState來識別,當呼叫SaveChanges時,執行相對應的SQL處理
Detached: 該實體尚未存在於DbContext中
Unchanged: 該實體剛從資料庫取出或是呼叫過SaveChanges之後,還沒有任何異動
Added: 該實體已經加入到DbContext中,但尚未呼叫SaveChanges
Deleted: 該實體已從DbContext中刪除,但尚未呼叫SaveChanges
Modifyied:該實體已在DbContext中更新過,但尚未調用SaveChanges
namespace ConsoleApplication1
{
using ConsoleApplication1.Models;
using System;
using System.Data.Entity;

class Program
{
static void Main(string[] args)
{
// 初始化資料庫
Database.SetInitializer(new MyInit());
using (DemoContext db = new DemoContext())
{
db.Database.Initialize(false);

// 建立一個新實體,初始狀態會是Detached
Topic topic = new Topic() { TopicTitle = “abc” };
Console.WriteLine(“{0}, {1}”, db.Topic.Local.Count, db.Entry(topic).State);

// 呼叫Attach可以把資料附加進Local集合中,狀態會是UnChanged
db.Topic.Attach(topic);
Console.WriteLine(“{0}, {1}”, db.Topic.Local.Count, db.Entry(topic).State);

// 把實體加入DbSet後,狀態會是Added
db.Topic.Add(topic);
Console.WriteLine(“{0}, {1}”, db.Topic.Local.Count, db.Entry(topic).State);

// 呼叫SaveChanges後,狀態會是UnChanged
db.SaveChanges();
Console.WriteLine(“{0}, {1}”, db.Topic.Local.Count, db.Entry(topic).State);

// 異動資料後,狀態會是Modified
topic.TopicTitle = “123”;
Console.WriteLine(“{0}, {1}”, db.Topic.Local.Count, db.Entry(topic).State);

// 把實體從DbSet移除後,狀態會是Deleted
db.Topic.Remove(topic);
Console.WriteLine(“{0}, {1}”, db.Topic.Local.Count, db.Entry(topic).State);
}
}
}
}


除了透過Entry取得實體的狀態外,還可以取得實體不同的值
目前的值(Current Value)
原始的值(Original Value)
資料庫裡面的值(Database Value)
namespace ConsoleApplication1
{
using ConsoleApplication1.Models;
using System;
using System.Data.Entity;

class Program
{
static void Main(string[] args)
{
// 初始化資料庫
Database.SetInitializer(new MyInit());
using (DemoContext db = new DemoContext())
{
db.Database.Initialize(false);

Topic topic = db.Topic.Find(1);
topic.TopicTitle = “123”;
db.Database.ExecuteSqlCommand(“UPDATE Topic SET TopicTitle=’456’ WHERE TopicID=1”);
Console.WriteLine(“CurrentValue:{0}”, db.Entry(topic).CurrentValues.GetValue<string>(“TopicTitle”));
Console.WriteLine(“OriginalValue:{0}”, db.Entry(topic).OriginalValues.GetValue<string>(“TopicTitle”));
Console.WriteLine(“DatabaseValue:{0}”, db.Entry(topic).GetDatabaseValues().GetValue<string>(“TopicTitle”));
}
}
}
}


如果不想加入Tracker的話,可以呼叫AsNoTracking()即可
namespace ConsoleApplication1
{
using ConsoleApplication1.Models;
using System;
using System.Data.Entity;

class Program
{
static void Main(string[] args)
{
// 初始化資料庫
Database.SetInitializer(new MyInit());
using (DemoContext db = new DemoContext())
{
db.Database.Initialize(false);

Console.WriteLine(db.Topic.Local.Count);
db.Topic.AsNoTracking().Load();
Console.WriteLine(db.Topic.Local.Count);
}
}
}
}