4

我曾经使用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

如herehere所述,似乎EntitiyFrameworkDataService不提供对底层DataService及其当前数据源的访问。因此,唯一的方法似乎是每次更改每个服务操作以创建一个新的数据上下文。

于 2013-11-13T14:16:14.923 回答