我有一个LINQ对象,并添加了一个额外的方法。该类没有一次性属性或方法,但FxCop提出错误“拥有一次性字段的类型应该是一次性的”并引用该类。
我已经减少了代码,但仍然收到错误:
partial class WikiPage
{
public PagePermissionSet GetUserPermissions(Guid? userId) {
using (WikiTomeDataContext context = new WikiTomeDataContext()) {
var permissions =
from wiki in context.Wikis
from pageTag in context.VirtualWikiPageTags
select new {};
return null;
}
}
}
但是,如果我删除from子句中的EITHER,FxCop会停止给出错误:
partial class WikiPage
{
public PagePermissionSet GetUserPermissions(Guid? userId) {
using (WikiTomeDataContext context = new WikiTomeDataContext()) {
var permissions =
from pageTag in context.VirtualWikiPageTags
select new {};
return null;
}
}
}
或者
partial class WikiPage
{
public PagePermissionSet GetUserPermissions(Guid? userId) {
using (WikiTomeDataContext context = new WikiTomeDataContext()) {
var permissions =
from wiki in context.Wikis
select new {};
return null;
}
}
}
PagePermissionSet不是一次性的。
这是假阳性吗?或者LINQ代码是否以某种方式在类中生成一次性字段?如果它不是误报,FxCop建议我实现IDisposable接口,但我会在Dispose方法中做什么?
编辑: 完整的FxCop错误是:
“在'WikiPage'上实现IDisposable,因为它 创建以下IDisposable类型的成员: 'WikiTomeDataContext'。如果'WikiPage'以前有过 发货,添加实现IDisposable的新成员 这种类型被认为是对现有的重大改变 消费者“。
编辑2: 这是引发错误的反汇编代码:
public PagePermissionSet GetUserPermissions(Guid? userId)
{
using (WikiTomeDataContext context = new WikiTomeDataContext())
{
ParameterExpression CS$0$0001;
ParameterExpression CS$0$0003;
var permissions = context.Wikis.SelectMany(Expression.Lambda<Func<Wiki, IEnumerable<VirtualWikiPageTag>>>(Expression.Property(Expression.Constant(context), (MethodInfo) methodof(WikiTomeDataContext.get_VirtualWikiPageTags)), new ParameterExpression[] { CS$0$0001 = Expression.Parameter(typeof(Wiki), "wiki") }), Expression.Lambda(Expression.New((ConstructorInfo) methodof(<>f__AnonymousType8..ctor), new Expression[0], new MethodInfo[0]), new ParameterExpression[] { CS$0$0001 = Expression.Parameter(typeof(Wiki), "wiki"), CS$0$0003 = Expression.Parameter(typeof(VirtualWikiPageTag), "pageTag") }));
return null;
}
}
编辑3: 似乎有一个包含对DataContext的引用的闭包类。这是它的反汇编代码:
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
// Fields
public WikiTomeDataContext context;
// Methods
public <>c__DisplayClass1();
}
答案 0 :(得分:3)
我的猜测是两个From
子句生成对SelectMany
的调用,并在数据上下文中使用闭包。闭包的实例有一个datacontext的字段,它导致FxCop警告。这没什么好担心的。
您的datacontext只有一个实例,您可以通过using块清理它。因为闭包没有终结器,所以FxCop警告中没有性能或安全含义。
答案 1 :(得分:2)
我注意到这是一个部分类。您是否检查了该类的其他实现文件,并查看它是否具有未被丢弃的IDisposable成员?
我不认为生成的闭包在这里有问题。使用某些属性生成闭包,这些属性应导致FxCop忽略此类警告。
编辑
OP的进一步调查显示,这是一个IDisposable字段被提升到关闭的问题。
不幸的是,你可以做很多事情。没有办法使闭包实现IDisposable。事件,如果你可以在闭包实例上无法调用IDisposable。
解决此问题的最佳方法是重写代码,使得在闭包中不会捕获一次性值。一次性字段在完成后应始终处理,并在关闭时捕获它会阻止您执行此操作。
答案 2 :(得分:1)
如果您从方法返回LINQ查询,消费者将使用foreach迭代结果。
当一个消费者完成一个foreach循环时,它在内部调用IEnumerable源上的dispose(在这种情况下,你的LINQ查询)。这将处理WikiTomeDataContext。
但是,如果消费者调用方法返回LINQ查询但从未迭代过结果,那么似乎永远不会丢弃可枚举(即,直到垃圾收集器清理对象)。这将导致您的WikiTomeDataContext在垃圾收集之前不会被处理。
你可以解决这个问题的一种方法是在你的LINQ查询结果上调用.ToArray,在你的上下文中调用dispose,然后返回数组。
答案 3 :(得分:0)
提供错误的代码使用WikiDataContext。
您的两个不提供错误的示例使用WikiTomeDataContext。
这两个导致错误的可能存在一些差异。