web-dev-qa-db-fra.com

Pourquoi trois propriétés de DbParameterCollection sont-elles abstraites dans les assemblages de référence mais virtuelles sinon?

Je déplace un projet de project.json Vers le nouveau format csproj, et il inclut une classe dérivée de DbParameterCollection . Dans mon vrai projet, j'utilise le multi-ciblage, mais pour les besoins de cette question, nous devons seulement nous préoccuper de net45.

Le compilateur me dit que je dois remplacer trois propriétés que je n'avais pas besoin auparavant:

Si vous suivez ces liens de documentation (qui sont pour .NET 4.5), vous verrez que toutes les propriétés sont virtuelles - pas abstraites. Si je crée le code simplement en appelant csc, tout va bien ... ce n'est que lors de l'utilisation du SDK .NET Core que je rencontre le problème.

Voici un exemple de code pour reproduire le problème:

Fichier de projet:

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

Code 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;
}

Les erreurs:

DummyParameterCollection.cs (5,14): erreur CS0534: 'DummyParameterCollection' n'implémente pas le membre abstrait hérité 'DbParameterCollection.IsSynchronized.get' [c:\Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]
DummyParameterCollection.cs (5,14): erreur CS0534: 'DummyParameterCollection' n'implémente pas le membre abstrait hérité 'DbParameterCollection.IsFixedSize.get' [c:\Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]
DummyParameterCollection.cs (5,14): erreur CS0534: 'DummyParameterCollection' n'implémente pas le membre abstrait hérité 'DbParameterCollection.IsReadOnly.get' [c:\Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]

Je crois que je connais la cause immédiate du problème, mais pas les raisons pourquoi c'est comme ça, ou la meilleure solution.

Il semble que le SDK .NET Core (et VS2017 lorsqu'il est chargé ce projet) utilise les assemblys de référence. Si j'ouvre C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll dans Reflector, cela montre aussi que les propriétés sont abstraites. Alors que si j'ouvre c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll, Cela montre que les propriétés sont virtuelles.

Je peux contourner ce problème en remplaçant les propriétés et en renvoyant simplement false de toutes - mais est-ce la meilleure façon de gérer cette situation? Au-delà de cela, y a-t-il une bonne raison pour laquelle les assemblys de référence ne correspondent pas aux assemblys réels (et à la documentation) dans ce cas? Je m'attendrais à ce que les assemblys de référence soient générés automatiquement, il est donc étrange que certaines choses soient incorrectes comme ceci ...

65
Jon Skeet

Les assemblages de référence sont corrects. Dans .NET Framework 4.5, ces propriétés étaient abstract. Ils ont été modifiés en virtual dans .NET Framework 4.5.1. Il semble que vous ayez découvert un bogue de documentation.

Comme vous l'avez probablement déjà deviné, la différence entre les deux assemblys System.Data.dll que vous observez est due à la façon dont .NET Framework sépare les assemblys de référence et les assemblys d'exécution. L'assembly de référence dans C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll reflète avec précision ce qui aurait été dans la version d'exécution 4.5 de System.Data.dll. Si vous pouvez obtenir une vieille machine qui n'a pas encore été mise à niveau vers .NET Framework 4.5.1 (bonne chance), vous trouverez cet assemblage d'exécution dans C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll a ces propriétés comme abstract. Mises à niveau de .NET Framework en place. Sur une machine mise à niveau vers .NET Framework 4.5.1 ou une version plus récente, C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll a été remplacé par la version mise à jour (avec virtual, pas abstract, propriétés.)

En ce qui concerne les solutions: compilez pour net451 à la place, ou la mise en œuvre de méthodes factices sont les meilleures approches. Vous pouvez faire d'autres astuces pour compiler avec une autre version de System.Data.dll, mais je ne le recommanderais pas

Je n'ai pas pu trouver de documentation officielle sur les changements d'API entre .NET Framework 4.5 et 4.5.1 ou une explication de la raison pour laquelle cela a été changé, cependant, j'ai trouvé ce commentaire d'un membre de l'équipe Entity Framework: https: //bugzilla.xamarin.com/show_bug.cgi?id=29167#c .

Les modifications suivantes (sans interruption) ont été apportées aux API System.Data dans la version .NET Framework 4.5.1 ....

Le membre suivant a été ajouté.

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

Le membre suivant est passé d'abstrait à virtuel.

  • 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