System.Data.Linq.Mapping.AttributedMetaDataMember High memory consumption

40 Views Asked by At

I'm analyzing the dump file for the Windows service project, and it is using LinqToSQL to connect databases. Attached dumpe heap memory analysis summary.

I can see the System.Data.Linq.Mapping.AttributedMetaDataMember taking more memory and It's resides in Gen2 bucket.

Can anyone guide me why it's taking more memory here?

Sample Code

public class Program
{
    static void Main(string[] args)
    {
        var detailsDataContext = new DetailsContext();
        var details = detailsDataContext.GetDetails(//param);
    }
}

public class DetailsContext
{
    private readonly IDetailsDataContextRepository _detailsDataContextRepository;

    public DetailsContext()
    {
        _detailsDataContextRepository = new DetailsDataContextRepository();
    }

    public Details GetDetails(string id)
    {
        try
        {
            List<Details> detailsList = _detailsDataContextRepository.GetDetails(id)?.ToList();
            if (detailsList != null && detailsList.Count > 0)
            {
                Detail detail = detailsList.FirstOrDefault();
                return detailsList;
            }

            return null;

        }
        catch (Exception ex)
        {
            //Error log
            return null;
        }
    }

}

public class DetailsDataContextRepository : DataContext, IDetailsDataContextRepository
{

    [Function(Name = "dbo.sp_GetDetails")]
    public IEnumerable<Details> GetDetails([Parameter(Name = "Id", DbType = "VARCHAR(255)")] string id)
    {
        try
        {
            IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), id);
            ISingleResult<Details> mRecord = ((ISingleResult<Details>)(result.ReturnValue));
            return mRecord;
        }
        catch (Exception ex)
        {
            TraceError("DetailsDataContext", "GetDetails", ex);
            return new List<Details>();
        }
    }
}

Thanks in Advance. enter image description here

1

There are 1 best solutions below

0
Joel Coehoorn On BEST ANSWER

I'll focus on DetailsContext.GetDetails(string id) method as one example of how to improve things.

Instead of this:

public Details GetDetails(string id)
{
    try
    {
        List<Details> detailsList = _detailsDataContextRepository.GetDetails(id)?.ToList();
        if (detailsList != null && detailsList.Count > 0)
        {
            Detail detail = detailsList.FirstOrDefault();
            return detailsList;
        }

        return null;

    }
    catch (Exception ex)
    {
        //Error log
        return null;
    }
}

You can get equivalent functionality like this:

public Details GetDetails(string id)
{
    try
    {
        return _detailsDataContextRepository.GetDetails(id).FirstOrDefault();
    }
    catch (Exception ex)
    {
        //Error log
        return null;
    }
}

Not only is this MUCH less code, but it's faster and far more memory efficient. As mentioned in the comment, one of the main improvements here is eliminating the spurious ToList() call, which accomplished nothing useful. I see a lot of programmers adopt this crutch, and learning to work without it can dramatically help your code.

Furthermore, based on a review of the repository's GetDetails() method, I might also remove the try/catch block, since that method itself uses a try/catch around anything that's likely to throw and provides a sensible default. It means we can safely get down to this one-liner with no loss of function:

public Details GetDetails(string id)
{
    return _detailsDataContextRepository.GetDetails(id).FirstOrDefault();
}