web-dev-qa-db-ja.com

DbParameterCollectionの3つのプロパティが参照アセンブリでは抽象的ですが、それ以外の場合はなぜ仮想ですか?

プロジェクトを_project.json_から新しいスタイルのcsproj形式に移動しています。これには DbParameterCollection から派生したクラスが含まれています。私の実際のプロジェクトではマルチターゲティングを使用していますが、この質問の目的のために、_net45_だけを気にする必要があります。

コンパイラは、以前は必要なかった3つのプロパティをオーバーライドする必要があると言っています。

これらのドキュメントリンク(.NET 4.5用)をたどると、すべてのプロパティがvirtual-抽象的ではないことがわかります。 cscを呼び出すだけでコードをビルドすると、すべてがうまくいきます...問題に遭遇するのは.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」は継承された抽象メンバー「DbParameterCollection.IsSynchronized.get」を実装しません[c:\ Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]
DummyParameterCollection.cs(5,14):エラーCS0534: 'DummyParameterCollection'は継承された抽象メンバー 'DbParameterCollection.IsFixedSize.get' [c:\ Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]を実装しません
DummyParameterCollection.cs(5,14):エラーCS0534:「DummyParameterCollection」は、継承された抽象メンバー「DbParameterCollection.IsReadOnly.get」を実装しません[c:\ Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]

私は問題の直接的な原因を知っていると思いますが、理由はわかりません理由それはこのような、または最善の回避策です。

.NET Core SDK(およびこのプロジェクトをロードしたときのVS2017)は参照アセンブリを使用しているようです。 ReflectorでC:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dllを開くと、thatはプロパティが抽象的であることも示します。一方、_c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll_を開くと、プロパティが仮想として表示されます。

プロパティをオーバーライドし、それらすべてからfalseを返すだけでこれを回避できますが、それがこの状況を処理する最良の方法ですか?それ以外に、この場合に参照アセンブリが実際のアセンブリ(およびドキュメント)と一致しない正当な理由はありますか?私は参照アセンブリが自動生成されることを期待しているので、someものがこのように間違っているのは奇妙です...

65
Jon Skeet

参照アセンブリは正しいです。 .NET Framework 4.5では、これらのプロパティはabstractでした。これらは、.NET Framework 4.5.1でvirtualに変更されました。ドキュメントのバグを発見したようです。

おそらく既に推測しているように、観察している2つの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.dllabstractとしてこれらのプロパティを持ちます。 .NET Frameworkのインプレースアップグレード。 .NET Framework 4.5.1以降にアップグレードしたマシンでは、C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dllは、更新されたバージョンに置き換えられました(プロパティは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#c

.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
21
natemcmaster