为什么在模型中添加对象的速度如此之慢?

时间:2014-12-08 14:37:19

标签: performance entity-framework optimization linq-to-entities

我有一个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; }
}

2 个答案:

答案 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);