4

以前は、.wcf データ サービス サービス操作内から (ef 5.0) エンティティのデータ コンテキストにアクセスしていましたthis.CurrentDataSource.MyEntity。私のデータ サービスは から継承されDataService<T>ました。エンティティ フレームワーク 6.0 を使用してインターネットで読みたいと思ったので、サービスを から継承する必要がありますEntityFrameworkDataService<T>。しかし、今ではサービス オペレーション内から、データ コンテキストにアクセスできなくなりました。this.CurrentDataSourceエンティティへの参照は含まれていません。

4

3 に答える 3

8

(キャッシュされた)リフレクション情報を介して基礎となるデータモデルを取得する拡張メソッドを使用した私の回避策は次のとおりです。現在の Microsoft.OData.EntityFrameworkProvider バージョン 1.0.0 alpha 2 で機能します。

使用例は、カスタム WebGet メソッド用です。

    [WebGet]
    public string GetMyEntityName(string myEntityKey)
    {
        var model = this.CurrentDataSource.GetDataModel();
        var entity = model.MyEntity.Find(myEntityKey);
        return entity.Name;
    }

そして実装:

public static class EntityFrameworkDataServiceProvider2Extensions
{
    /// <summary>
    /// Gets the underlying data model currently used by an EntityFrameworkDataServiceProvider2.
    /// </summary>
    /// <remarks>
    /// TODO: Obsolete this method if the API changes to support access to the model.
    /// Reflection is used as a workaround because EntityFrameworkDataServiceProvider2 doesn't (yet) provide access to its underlying data source. 
    /// </remarks>
    public static T GetDataModel<T>(this EntityFrameworkDataServiceProvider2<T> efProvider) where T : class
    {
        if (efProvider != null)
        {
            Type modelType = typeof(T);

            // Get the innerProvider field info for an EntityFrameworkDataServiceProvider2 of the requested type
            FieldInfo ipField;
            if (!InnerProviderFieldInfoCache.TryGetValue(modelType, out ipField))
            {
                ipField = efProvider.GetType().GetField("innerProvider", BindingFlags.NonPublic | BindingFlags.Instance);
                InnerProviderFieldInfoCache.Add(modelType, ipField);
            }

            var innerProvider = ipField.GetValue(efProvider);
            if (innerProvider != null)
            {
                // Get the CurrentDataSource property of the innerProvider
                PropertyInfo cdsProperty;
                if (!CurrentDataSourcePropertyInfoCache.TryGetValue(modelType, out cdsProperty))
                {
                    cdsProperty = innerProvider.GetType().GetProperty("CurrentDataSource");
                    CurrentDataSourcePropertyInfoCache.Add(modelType, cdsProperty);
                }
                return cdsProperty.GetValue(innerProvider, null) as T;
            }
        }
        return null;
    }

    private static readonly ConditionalWeakTable<Type, FieldInfo> InnerProviderFieldInfoCache = new ConditionalWeakTable<Type, FieldInfo>();
    private static readonly ConditionalWeakTable<Type, PropertyInfo> CurrentDataSourcePropertyInfoCache = new ConditionalWeakTable<Type, PropertyInfo>();
}

System.Runtime.CompilerServices.ConditionalWeakTableは、リフレクション データのキャッシングから得られた提案に基づいて、リフレクション結果をキャッシュするために使用されました。

于 2014-01-03T05:08:11.447 に答える
1

出来た!VB.NET で変換したコードを次に示します。

Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Data.Services.Providers

Public Module EntityFrameworkDataServiceProvider2Extensions

    ''' <summary>
    ''' Gets the underlying data model currently used by an EntityFrameworkDataServiceProvider2.
    ''' </summary>
    ''' <remarks>
    ''' TODO: Obsolete this method if the API changes to support access to the model.
    ''' Reflection is used as a workaround because EntityFrameworkDataServiceProvider2 doesn't (yet) provide access to its underlying data source. 
    ''' </remarks>
    <System.Runtime.CompilerServices.Extension> _
    Public Function GetDataModel(Of T As Class)(efProvider As EntityFrameworkDataServiceProvider2(Of T)) As T
        If efProvider IsNot Nothing Then
            Dim modelType As Type = GetType(T)

            ' Get the innerProvider field info for an EntityFrameworkDataServiceProvider2 of the requested type
            Dim ipField As FieldInfo = Nothing
            If Not InnerProviderFieldInfoCache.TryGetValue(modelType, ipField) Then
                ipField = efProvider.[GetType]().GetField("innerProvider", BindingFlags.NonPublic Or BindingFlags.Instance)
                InnerProviderFieldInfoCache.Add(modelType, ipField)
            End If

            Dim innerProvider = ipField.GetValue(efProvider)
            If innerProvider IsNot Nothing Then
                ' Get the CurrentDataSource property of the innerProvider
                Dim cdsProperty As PropertyInfo = Nothing
                If Not CurrentDataSourcePropertyInfoCache.TryGetValue(modelType, cdsProperty) Then
                    cdsProperty = innerProvider.[GetType]().GetProperty("CurrentDataSource")
                    CurrentDataSourcePropertyInfoCache.Add(modelType, cdsProperty)
                End If
                Return TryCast(cdsProperty.GetValue(innerProvider, Nothing), T)
            End If
        End If
        Return Nothing
    End Function

    Private ReadOnly InnerProviderFieldInfoCache As New ConditionalWeakTable(Of Type, FieldInfo)()
    Private ReadOnly CurrentDataSourcePropertyInfoCache As New ConditionalWeakTable(Of Type, PropertyInfo)()
End Module
于 2014-02-15T20:42:06.377 に答える
0

hereおよびhereに記載されているように、 は基になるデータソースとその現在のデータソースへのアクセスを提供してEntitiyFrameworkDataServiceいないようです。そのため、各サービス操作を変更して毎回新しいデータ コンテキストを作成する唯一の方法と思われます。DataService

于 2013-11-13T14:16:14.923 に答える