为什么引用程序集中的DbParameterCollection抽象中有三个属性,否则是虚拟的?

我将项目从project.json移动到新样式的csproj格式,它包含从DbParameterCollection派生的类。 在我真正的项目中,我正在使用多目标,但为了这个问题的目的,我们只需要关心net45

编译器告诉我,我必须重写以前没有的三个属性:

  • IsFixedSize
  • IsReadOnly
  • IsSynchronized

如果你遵循这些文档链接(这是用于.NET 4.5),你会看到所有的属性是虚拟的 – 而不是抽象的。 如果我只是通过调用csc构build代码,一切都很好……只有在使用.NET Core SDK时才会遇到问题。

以下是重现问题的示例代码:

项目文件:

 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net45</TargetFramework> </PropertyGroup> </Project> 

C#代码:

 using System; using System.Collections; using System.Data.Common; public class DummyParameterCollection : DbParameterCollection { public override int Count => 0; public override object SyncRoot => null; public override void Remove(object value) {} public override void RemoveAt(int index) {} public override void RemoveAt(string parameterName) {} public override int Add(object value) => 0; public override void Insert(int index, object value) {} public override void AddRange(Array values) {} public override void Clear() {} public override bool Contains(object value) => false; public override bool Contains(string value) => false; public override void CopyTo(Array array, int index) {} public override int IndexOf(object value) => -1; public override int IndexOf(string parameterName) => -1; protected override DbParameter GetParameter(int index) => null; protected override DbParameter GetParameter(string parameterName) => null; protected override void SetParameter(int index, DbParameter value) {} protected override void SetParameter(string parameterName, DbParameter value) {} public override IEnumerator GetEnumerator() => null; } 

错误:

DummyParameterCollection.cs(5,14):错误CS0534:'DummyParameterCollection'没有实现inheritance的抽象成员'DbParameterCollection.IsSynchronized.get'[c:\ Users \ skeet \ Test \ ParameterCollection \ ParameterCollection.csproj]
DummyParameterCollection.cs(5,14):错误CS0534:'DummyParameterCollection'没有实现inheritance的抽象成员'DbParameterCollection.IsFixedSize.get'[c:\ Users \ skeet \ Test \ ParameterCollection \ ParameterCollection.csproj]
DummyParameterCollection.cs(5,14):错误CS0534:'DummyParameterCollection'没有实现inheritance的抽象成员'DbParameterCollection.IsReadOnly.get'[c:\ Users \ skeet \ Test \ ParameterCollection \ ParameterCollection.csproj]

我相信我知道问题的直接原因,但不是这个原因,或者最好的解决方法。

它看起来像.NET核心SDK(和VS2017当它加载这个项目)使用引用程序集。 如果我在Reflector中打开C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll那么也显示属性是抽象的。 而如果我打开c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll ,则显示属性为虚拟。

我可以通过覆盖这些属性来解决这个问题,只是从所有这些属性中返回false ,但这是处理这种情况的最好方法吗? 除此之外,在这种情况下,引用程序集与实际程序集(和文档)不匹配的原因是否有充分的理由? 我期望引用程序集是自动生成的,所以有些事情是不正确的,这是奇怪的…

参考assembly是正确的。 在.NET Framework 4.5中,这些属性是abstract 。 他们在.NET Framework 4.5.1中被更改为virtual 。 看来你已经发现了一个文档错误。

正如你可能已经猜到的那样,你所观察到的两个System.Data.dll程序集之间的区别是由于.NET Framework分离参考程序集和运行时程序集。 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll的引用程序集准确地反映了4.5版运行时版本的System.Data.dll 。 如果您能够获得尚未升级到.NET Framework 4.5.1的旧机器(祝您好运),您将在C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dllfind该运行时assemblyC:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll具有这些属性作为abstract 。 .NET Framework就地升级。 在已升级到.NET Framework 4.5.1或更高版本的计算机上,已将C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dllreplace为更新后的版本(使用virtual而不是abstract ,属性。)

就解决方法而言:代替net451编译,或者实施虚拟方法是最好的方法。 你可以做其他技巧编译对不同版本的System.Data.dll,但我不会推荐它

我找不到有关.NET Framework 4.5和4.5.1之间的API更改的官方文档,或者为什么会更改此解释,但是,我从Entity Framework团队的成员发现了此评论: https:// bugzilla。 xamarin.com/show_bug.cgi?id=29167#c0 。

在.NET Framework 4.5.1发行版中对System.Data API进行了以下(非重复)更改….

以下成员被添加。

  • System.Data.Common.DbParameter.Precision
  • System.Data.Common.DbParameter.Scale
  • System.Data.SqlClient.SqlConnectionStringBuilder.ConnectRetryCount
  • System.Data.SqlClient.SqlConnectionStringBuilder.ConnectRetryInterval

以下成员从抽象变为虚拟。

  • System.Data.Common.DbDataReader.Close
  • System.Data.Common.DbDataReader.GetSchemaTable
  • System.Data.Common.DbParameter.SourceVersion
  • System.Data.Common.DbParameterCollection.IsFixedSize
  • System.Data.Common.DbParameterCollection.IsReadOnly
  • System.Data.Common.DbParameterCollection.IsSynchronized