您是否真的对您的代码进行了分析?请参阅Erik Lippert的performance rant:使用分析器或其他分析工具在开始调查替代方法之前根据经验确定瓶颈的位置。例如,您的实际性能问题可能在BabysFirstsUsersDataEntities db
类中。
这就是说,我的直接反应是你有太多的数据中间表示,建设,人口和垃圾收集都需要时间。这些措施包括:
- 可能大到足以走在large object heap,从而永久性地损害性能和内存使用的过程的
jsonString
。
- 您的整个JSON层次结构的
JToken tok
表示形式。每个人JsonUserImageDTO
。
我建议的是尽可能多地消除这些中间表示。如the documentation中所建议的,您应该直接从流中加载,而不是加载到字符串并解析该字符串。
您也可以通过直接填充数据模型来消除JToken tok
。比方说,你的BabysFirstsUsersDataEntities
看起来像这样(我只是猜测这里):
public class BabysFirstsUsersDataEntities
{
public BabysFirstsUsersDataEntities() { this.UserImageLists = new List<UserImageList>(); }
public List<UserImageList> UserImageLists { get; set; }
}
public class UserImageList
{
public string email { get; set; }
public List<string> urlList;
}
而且你的DTO模式看起来是这样的模型由http://json2csharp.com/提供:
public class RootObjectDTO
{
public ICollection<JsonUserImageDTO> results { get; set; }
}
public class JsonUserImageDTO
{
public ACL ACL { get; set; }
public string REID { get; set; }
public string createdAt { get; set; }
public string email { get; set; }
public string objectId { get; set; }
public string updatedAt { get; set; }
public int urlCount { get; set; }
public List<string> urlList { get; set; }
public UserImageList ToDataModel()
{
return new UserImageList { email = email, urlList = urlList };
}
}
public class Asdf
{
public bool read { get; set; }
public bool write { get; set; }
}
public class RoleAdmin
{
public bool read { get; set; }
}
public class ACL
{
public Asdf asdf { get; set; }
[JsonProperty("role:admin")]
public RoleAdmin RoleAdmin { get; set; }
}
然后创建下列通用ConvertingCollection<TIn, TOut>
工具类:
public class ConvertingCollection<TIn, TOut> : BaseConvertingCollection<TIn, TOut, ICollection<TIn>>
{
readonly Func<TOut, TIn> toInner;
public ConvertingCollection(Func<ICollection<TIn>> getCollection, Func<TIn, TOut> toOuter, Func<TOut, TIn> toInner)
: base(getCollection, toOuter)
{
if (toInner == null)
throw new ArgumentNullException();
this.toInner = toInner;
}
protected TIn ToInner(TOut outer) { return toInner(outer); }
public override void Add(TOut item)
{
Collection.Add(ToInner(item));
}
public override void Clear()
{
Collection.Clear();
}
public override bool IsReadOnly { get { return Collection.IsReadOnly; } }
public override bool Remove(TOut item)
{
return Collection.Remove(ToInner(item));
}
public override bool Contains(TOut item)
{
return Collection.Contains(ToInner(item));
}
}
public abstract class BaseConvertingCollection<TIn, TOut, TCollection> : ICollection<TOut>
where TCollection : ICollection<TIn>
{
readonly Func<TCollection> getCollection;
readonly Func<TIn, TOut> toOuter;
public BaseConvertingCollection(Func<TCollection> getCollection, Func<TIn, TOut> toOuter)
{
if (getCollection == null || toOuter == null)
throw new ArgumentNullException();
this.getCollection = getCollection;
this.toOuter = toOuter;
}
protected TCollection Collection { get { return getCollection(); } }
protected TOut ToOuter(TIn inner) { return toOuter(inner); }
#region ICollection<TOut> Members
public abstract void Add(TOut item);
public abstract void Clear();
public virtual bool Contains(TOut item)
{
var comparer = EqualityComparer<TOut>.Default;
foreach (var member in Collection)
if (comparer.Equals(item, ToOuter(member)))
return true;
return false;
}
public void CopyTo(TOut[] array, int arrayIndex)
{
foreach (var item in this)
array[arrayIndex++] = item;
}
public int Count { get { return Collection.Count; } }
public abstract bool IsReadOnly { get; }
public abstract bool Remove(TOut item);
#endregion
#region IEnumerable<TOut> Members
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in Collection)
yield return ToOuter(item);
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
现在,您可以填充你的db
直接如下:
var rootDTO = new RootObjectDTO
{
results = new ConvertingCollection<UserImageList, JsonUserImageDTO>(() => db.UserImageLists, (x) => { throw new NotImplementedException(); }, (x) => x.ToDataModel())
};
using (var stream = File.Open(path, FileMode.Open))
using (var reader = new StreamReader(stream))
{
JsonSerializer.CreateDefault().Populate(reader, rootDTO);
}
通过填充预分配rootDTO
和ConvertingCollection<UserImageList, JsonUserImageDTO>
,你db.UserImageLists
将得到填充了JSON的用更少的中间表示的内容。
1)您应该直接从'Stream'加载(http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JToken_Load.htm),而不是加载到大的中间字符串,然后解析字符串,正如[这里](http://www.newtonsoft.com/json/help/html/Performance.htm)所解释的那样。 2)为什么内部循环内部的path.Contains(“UserImageList”)?如果这不是真的,你不能完全跳过文件吗? – dbc
我将签出#1并回报...#2指的是文件的名称,它是我执行时处理的不同文件类型对应于不同模型的剩余部分。我现在会改变它,因为它使事情看起来比它们更复杂 – Jaked222
像这样? StreamReader sr = new StreamReader(path); JsonReader reader = new JsonTextReader(sr); var tok = JObject.Load(reader); – Jaked222