Entity infrastructure data context 6 from wcf data service

I used to access the data context of my (ef 5.0) objects from the wcf c data services service this.CurrentDataSource.MyEntity. My data service is inherited from DataService<T>. Now I wanted to use the framework 6.0 entity and read on the Internet, I have to inherit the service from EntityFrameworkDataService<T>. But now, from within my service operations, I can no longer access my data context. this.CurrentDataSourcedoes not contain references to objects.

+4
source share
3 answers

Here my workaround is using an extension method that gets the underlying data model through the (cached) reflection information. It works for the current version of Microsoft.OData.EntityFrameworkProvider version 1.0.0 alpha 2.

Using the example for a custom WebGet method:

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

And implementation:

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 was used to cache reflection results based on a sentence taken from Reflection Caching Data

+8
source

It worked! Here is the code converted to 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
+1
source

, EntitiyFrameworkDataService DataService , . , , -, .

0

All Articles