我有一个SimID查询,它将给定的手机号码列表与我们的数据库中的各自ID相连,如果数字在数据库中不存在,则返回0作为ID。如果我在调试时查看我的查询,它会非常快速地执行。但是,当我遍历查询结果并创建一个新对象并将其添加到我的模型时,创建458个新对象需要3分钟。
我是EF和Linq的新手,我做错了什么?如何优化此代码以更快地执行?
非常感谢任何帮助。
//Query to create virtual table of SimID and MSISDN joined on Cache.MSISDN
var SimID = (from ca_msisdn in Cache.MSISDN
join db_simobj in ctx.Sims on ca_msisdn equals db_simobj.Msisdn into Holder
from msisdnresult in Holder.DefaultIfEmpty()
select new { MSISDN = ca_msisdn, ID = (msisdnresult == null || msisdnresult.SimId == 0 ? 0 : msisdnresult.SimId) });
//Loop through virtual tables and add new data to model
foreach (var ToUpdate in SimID)
{
if (ToUpdate.ID == 0)
{
Console.WriteLine("We have found a new MSISDN: " + ToUpdate.MSISDN + " adding it to the model.");
ctx.Sims.Add(new Sim { Msisdn = ToUpdate.MSISDN });
}
}
//My Sim object
public partial class Sim
{
public Sim()
{
this.CDR_Event = new HashSet<CDR_Event>();
}
public long SimId { get; set; }
public long SimStatusId { get; set; }
public Nullable<long> FitmentCentreId { get; set; }
public string Serial { get; set; }
public string Msisdn { get; set; }
public string Puk { get; set; }
public string Network { get; set; }
public Nullable<System.DateTime> SimStatusDate { get; set; }
public Nullable<System.DateTime> ActivationDate { get; set; }
public Nullable<System.DateTime> ExpiryDate { get; set; }
public Nullable<long> APNSimStatusId { get; set; }
public Nullable<System.DateTime> APNActivated { get; set; }
public Nullable<System.DateTime> APNConfirmed { get; set; }
public string Svr { get; set; }
public virtual ICollection<CDR_Event> CDR_Event { get; set; }
}
答案 0 :(得分:1)
您的主要问题是,每次在上下文中添加Sims
集合时,您都会添加上下文的更改跟踪器需要跟踪的内容,这可能会成为一个非常昂贵的内存命题。你开始拥有更多的实体。
您可以通过以下两种方式解决此问题:
1)批量保存数据。这样,变更跟踪器就不必跟踪大量添加的实体。
2)如果您不想立即保存,请先将其保存为内存列表,然后在保存这些记录时执行#1。
答案 1 :(得分:0)
IronMan84提到的这个问题的答案;记录here的目的是使用.AddRange()并将所有内容一次性添加为foreach之外的列表,而不是在循环内逐个添加。
List<Sim> _SIMS = new List<Sim>();
foreach (var ToUpdate in SimID)
{
if (ToUpdate.ID == 0)
{
Console.WriteLine("We have found a new MSISDN: " + ToUpdate.MSISDN + " adding it to the model.");
_SIMS.Add(new Sim { Msisdn = ToUpdate.MSISDN} );
}
}
ctx.Sims.AddRange(_SIMS);