1. 程式人生 > >解決Newtonsoft.json將資料庫實體表序列化為json時提示此例項已被釋放的錯誤

解決Newtonsoft.json將資料庫實體表序列化為json時提示此例項已被釋放的錯誤

Newtonsoft.json版本:10.0.0.0

資料庫:sqlserver2008r2

Entity Framework版本:5.0.0

EF查詢語句如下:

public DBResult<List<H_MES_USERS>> GetUsers()
        {
            DBResult<List<H_MES_USERS>> Result = new DBResult<List<H_MES_USERS>>();
            try
            {                
                using (HCN_M_DATAEntities entities = new HCN_M_DATAEntities())
                {
                    Result.Data = entities.H_MES_USERS.ToList();
                    Result.Success = true;
                }                
            }
            catch (Exception ex)
            {
                WriteLog.WriteLogFile(this.GetType(), LogLevel.ERROR, ex.ToString());         
            }
            
            return Result;
        }

JSON轉換如下:

public static string ObjToJson<T>(T obj)
        {
            try
            {            
                return JsonConvert.SerializeObject(obj);
            }
            catch (Exception ex)
            {             
                WriteLog.WriteLogFile(typeof(NewtonJsonConvert), LogLevel.ERROR, ex.ToString()); 
                return null;
            }
        }
H_MES_USERS的ID是H_MES_USERROLE表的UserID欄位的外來鍵。

出現此錯誤的原因是被序列化的資料庫表與其他表有外來鍵的關係,你用EF查詢H_MES_USERS,EF會建立與H_MES_USERROLE表的對映關係,這種對映關係是基於資料庫中的外來鍵建立的。也就是說當序列化JSON在using (HCN_M_DATAEntities entities = new HCN_M_DATAEntities())這個範圍內時,JsonConvert.SerializeObject這個函式就可以找到這種對映關係,即可以完成序列化。當在這個範圍外序列號時,因為資料庫的連線已經關閉了,所以無法找到這種對映關係,才會提示此例項已被釋放的錯誤。

解決的方法有兩種:

1、在自動生成的EF實體類H_MES_USERS的 H_MES_USERROLE 屬性上新增[JsonIgnore]特性。

[JsonIgnore]
public virtual ICollection<H_MES_USERROLE> H_MES_USERROLE { get; set; }

當然還必須在實體類H_MES_USERS中新增using Newtonsoft.Json;

這種方式的告訴JSON轉換器不用去管外來鍵的對映關係。

2、

entities.H_MES_USERS.ToList().Select(u => new H_MES_USERS() { ID = u.ID,UserName = u.UserName}).ToList(); 

當你只需要H_MES_USERS中的幾個欄位時,可以在select裡面new一個H_MES_USERS物件,此時的H_MES_USERS物件只是一個實體類,與H_MES_USERROLE表的對映關係也沒有了,所以序列化JSON的時候就不會去查詢對映關係。

關於網上流傳的在做JSON轉換的時候設定引數,這種方式為也是過了,好像沒什麼用,程式碼如下:

JsonSerializerSettings setting = new JsonSerializerSettings();
setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
setting.MissingMemberHandling = MissingMemberHandling.Ignore;
return JsonConvert.SerializeObject(obj,setting);
這兩個屬性我都試過了,好像都沒效果。