2014-10-10 195 views
0

目前我正在使用[JsonIgnore]屬性來避免模型中的循環引用。但我認爲,它將應用於所有實現。如何避免在Linq to Sql查詢中循環循環?

現在我使用像這個 -

我有兩個型號:

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string ProjectName { get; set; } 

    public DateTime? EstimatedEndDate { get; set; } 
    public DateTime? ProjectStartDate { get; set; } 
    public string OrderNumber { get; set; } 

    public string ProjectDescription { get; set; } 
    public virtual List<ServiceObject> ServiceObjects { get; set; } 

    [Required] 
    public string RegardingUser { get; set; } 

    public string CreatedBy { get; set; } 
    public DateTime CreatedDate { get; set; } 
    public string ModifiedBy { get; set; } 
    public DateTime ModifiedDate { get; set; } 
    public bool IsProjectDeleted { get; set; } 
    [NotMapped] 
    public int? ServiceObjectTemplateID { get; set; } 

} 

彼此型號是 -

public class ServiceObject 
{ 
    public int ServiceObjectID { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string RegardingUser { get; set; } 
    public int? ParentServiceObjectID { get; set; } 
    [ForeignKey("ParentServiceObjectID")] 
    public virtual List<ServiceObject> ServiceObjects { get; set; } 
    public int ProjectID { get; set; } 
    [JsonIgnore] 
    public virtual Project Project { get; set; }<--------------------------- 
    public virtual List<ServicePicture> ServicePictures { get; set; } 
    public bool IsServiceObjectDeleted { get; set; } 
    public string CreatedBy { get; set; } 
    public DateTime CreatedDate { get; set; } 
    public string ModifiedBy { get; set; } 
    public DateTime ModifiedDate { get; set; } 
} 

但我想申請JsonIgnore財產或任何其他屬性在Linq to Sql中查詢自己。我的意思是我想動態應用它。

查詢是喜歡 -

var projectList = (from pro in context.Projects.All 
        select pro).ToList(); 

我希望有條件地適用。

在此先感謝。

+0

屬性必須在編譯時應用,因此不能動態添加它們。 – TGH 2014-10-10 04:13:46

+0

這意味着它將只適用於模型? – Abhinav 2014-10-10 04:15:34

+0

是的,你必須在編譯時將它們應用到你的屬性。 – TGH 2014-10-10 04:16:29

回答

1

好的,根據您的意見和我的猜測,您所看到的是一個典型的EF代碼優先問題。 EF爲您的每個實體生成動態代理,以便它可以跟蹤對其的更改。但是,這使得系列化困難,因爲它們被創建爲dynamic對象。有一些方法可以避免這一點:

選項A:禁用代理的創建只是針對特定的查詢:

// disable proxy creation just for the duration of query 
context.Configuration.ProxyCreationEnabled = false; 

// do the query, serialize, go crazy! 

// enable proxy again. or if your context goes out of scope after this call, then you can ignore re-enabling. 
context.Configuration.ProxyCreationEnabled = true; 

選項B:如果你不打算修改,並在一些更新實體稍後點

var entity = context.Where(...); // or whatever query 

// detach entity 
context.Entry(entity).State = EntityState.Detached; 

選項C:通過修改類型定義避免代理:

如果您創建不帶虛擬屬性的密封類型或類型,EF將不會創建代理,因爲 對代理無效。

public sealed class Project {...} 

// or make it non virtual 
... 
public List<ServiceObject> ServiceObjects { get; set; } 
... 

注意,在這種情況下,你必須手動加載相關對象:

context.Projects.Include(p => p.ServiceObjects).ToList(); 

選項d:禁用代理的創建永久:

// in your initializer or DbContext class' constructor 
DbContext.Configuration.ProxyCreationEnabled = false; 

注意 :如果禁用代理創建,EF將不會跟蹤更改a utomatically。您可以使用快照方法manually track them

根據您的設計,您可以按照其中一個或多個選項進行操作。我通常堅持使用選項A或B.

+0

謝謝你給我幾個解決方案。所有的解決方案都很好。我希望所有這些方式都是標準方法。 :) – Abhinav 2014-10-11 03:07:24

+0

這些都是我知道的正式記錄的方式。 – Mrchief 2014-10-11 13:37:18

+0

我認爲'ProxyCreationEnabled'只適用於實體框架,而不是Linq to SQL,提問者詢問關於Linq到SQL – 2017-10-11 13:34:16

2

XY問題。你的實際問題是「我想在運行時控制哪些屬性被序列化」。

控制哪些屬性被序列化的最常見方法是使用JsonIgnoreAttribute。然而正如其他人所說的那樣,屬性是在編譯時應用的,並且通常不能在運行時進行修改(您也不希望這樣做,因爲它實際上是在運行時更改的全局設置,所以會遇到大量線程問題)。

相反,答案是使用IContractResolver接口來改變序列化行爲。

public class OmitPropertyContractResolver 
     : IContractResolver 
{ 
    private readonly string[] _ignoredProperties; 
    private readonly IContractResolver _resolver; 

    public OmitPropertyContractResolver(IContractResolver resolver, params string[] ignoredProperties) 
    { 
     _ignoredProperties = ignoredProperties; 
     _resolver = resolver;   
    } 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     var properties = _resolver.CreateProperties(type, memberSerialization); 
     return properties 
       .Where(p => _ignoredProperties.Contains(p.Name) == false) 
       .ToList(); 
    } 
} 

另一種可能是在你的Json.net設置,使用ReferenceLoopHandling設置。

var serializer = new JsonSerializer(
         new JsonSerializerSetting() 
           { 
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
           }); 

這將只序列化每個對象一次。

最後一個選項是使用ItemReferenceLoopHandling。這是序列化(和反序列化)具有循環引用的對象圖(註釋,圖形而不是樹)的非標準方式。

此方法的缺點是它是非標準的,可能無法在客戶端上工作。

+0

嗯...其實我的應用程序完全是客戶端應用程序。 – Abhinav 2014-10-10 09:04:35