簡體   English   中英

來自wcf數據服務的實體框架6數據上下文

[英]Entity framework 6 data context from wcf data service

我曾經使用this.CurrentDataSource.MyEntity從wcf數據服務服務操作中訪問my(ef 5.0)實體的數據上下文。 我的數據服務繼承自DataService<T> 現在我想使用實體框架6.0並在互聯網上閱讀,我應該從EntityFrameworkDataService<T>繼承服務。 但是現在從我的服務操作中,我再也無法訪問我的數據上下文了。 this.CurrentDataSource不包含對實體的任何引用。

這是我的解決方法,使用擴展方法通過(緩存)反射信息獲取基礎數據模型。 它適用於當前的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用於根據緩存反射數據中的建議緩存反射結果

有效! 這是用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

似乎EntitiyFrameworkDataService不提供對底層DataService及其當前數據源的訪問,如此此處所述 因此,唯一的方法似乎是每次都改變每個服務操作以創建新的數據上下文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM