英文:
System.Data.Linq.Mapping.AttributedMetaDataMember High memory consumption
问题
我正在分析Windows服务项目的转储文件,它使用LinqToSQL来连接数据库。附上堆内存分析摘要。
我可以看到System.Data.Linq.Mapping.AttributedMetaDataMember占用了更多内存,它位于Gen2桶中。
有人可以指导我为什么它在这里占用更多内存吗?
示例代码
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>();
}
}
}
提前感谢。
英文:
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>();
}
}
}
答案1
得分: 2
我将专注于 DetailsContext.GetDetails(string id)
方法,作为如何改进事情的一个示例。
替代以下内容:
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)
{
//错误日志
return null;
}
}
你可以获得等效的功能,像这样:
public Details GetDetails(string id)
{
try
{
return _detailsDataContextRepository.GetDetails(id).FirstOrDefault();
}
catch (Exception ex)
{
//错误日志
return null;
}
}
不仅代码少得多,而且速度更快,内存效率更高。正如评论中提到的,这里的主要改进之一是消除了多余的 ToList()
调用,这没有做任何有用的事情。我看到很多程序员采用这种方法,学会不使用它可以显著帮助你的代码。
此外,根据对存储库的 GetDetails()
方法的审查,我还可以删除 try/catch
块,因为该方法本身在可能引发异常的任何地方都使用了 try/catch
并提供了合理的默认值。这意味着我们可以安全地将代码简化为这一行,而不会损失功能:
public Details GetDetails(string id)
{
return _detailsDataContextRepository.GetDetails(id).FirstOrDefault();
}
英文:
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();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论