Проблема
Иногда возникает потребность использовать в одном приложении объекты, которые должны храниться в разных типах хранилищ. Например, статистические данные, которые могут накапливаться в значительных объемах, при этом, отсутствует необходимость, в сложных выборках и их частом изменении. Решением подобной проблемы может быть использование для таких данных NoSQL хранилища, например MongoDB.
Решения
Регистрация нескольких ODataService
’ов
По умолчанию, определения сервиса данных для ODataService
выполняется с помощью механизма внедрения зависимости Unity Container
.
Изменить логику определения сервиса данных, можно, заменив сервис, реализующий интерфейс IHttpControllerActivator
, как показано на примере ниже:
namespace IIS.MyProject
{
using System;
internal static class ODataConfig
{
public static void Configure(HttpConfiguration config, IUnityContainer container)
{
// Use Unity as WebAPI dependency resolver
config.DependencyResolver = new UnityDependencyResolver(container);
// Map OData Service with basic objects
config.MapODataServiceDataObjectRoute(new DefaultDataObjectEdmModelBuilder(new[]
{
Assembly.Load("MyProject.Objects"),
}));
// Map OData Service with service objects
config.MapODataServiceDataObjectRoute(new DefaultDataObjectEdmModelBuilder(new[]
{
typeof(ApplicationLog).Assembly,
typeof(UserSetting).Assembly,
typeof(FlexberryUserSetting).Assembly,
typeof(Lock).Assembly
}), "service", "service");
// Replace IHttpControllerActivator service
config.Services.Replace(typeof(IHttpControllerActivator), new ControllerActivator(container));
}
}
}
MapODataServiceDataObjectRoute
, в противном случае он будет повторно заменен реализацией NewPlatform.Flexberry.ORM.ODataService.DataObjectControllerActivator
Сервис, реализующий интерфейс IHttpControllerActivator
, может быть примерно следующим:
namespace IIS.MyProject
{
using System;
public class ControllerActivator : IHttpControllerActivator
{
private readonly IUnityContainer _container;
private readonly IHttpControllerActivator _defaultActivator;
public ControllerActivator(IUnityContainer container)
{
_container = container;
_defaultActivator = new DefaultHttpControllerActivator();
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
if (controllerDescriptor.ControllerName == "DataObject")
{
ManagementToken token = request.GetODataServiceToken();
string dataServiceName = null;
if (token.Route.RoutePrefix == "odata")
dataServiceName = "MSSQLDataService";
else if (token.Route.RoutePrefix == "service")
dataServiceName = "MongoDbDataService";
return new DataObjectController(_container.Resolve<IDataService>(dataServiceName), token.Model, token.Events, token.Functions);
}
return _defaultActivator.Create(request, controllerDescriptor, controllerType);
}
}
}
В данном случае, при обращении к ODataService
зарегистрированному на маршруте service
, будет использована именованая регистрация IDataService
с именем MongoDbDataService
, при обращении к ODataService
зарегистрированному на маршруте odata
, будет использована именованая регистрация IDataService
с именем MSSQLDataService
.
Пример конфигурации для данного сервиса:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- ... -->
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register name="MongoDbDataService" type="ICSSoft.STORMNET.Business.IDataService, ICSSoft.STORMNET.Business" mapTo="NewPlatform.Flexberry.ORM.MongoDbDataService, NewPlatform.Flexberry.ORM.MongoDbDataService">
<constructor />
<property name="CustomizationString" value="SERVER=server;Trusted_connection=yes;DATABASE=database;" />
</register>
<register name="MSSQLDataService" type="ICSSoft.STORMNET.Business.IDataService, ICSSoft.STORMNET.Business" mapTo="ICSSoft.STORMNET.Business.MSSQLDataService, ICSSoft.STORMNET.Business.MSSQLDataService">
<constructor />
<property name="CustomizationString" value="SERVER=server;Trusted_connection=yes;DATABASE=database;" />
</register>
<!-- ... -->
</container>
</unity>
</configuration>
ember
-приложении потребуется настройка адаптеров.Определение типа сервиса данных по типу объектов
Также определять тип необходимого сервиса данных, можно, на основе типа объектов данных, к которым идет обращение, в данном случае можно зарегистрировать один ODataService
, как в примере ниже:
namespace IIS.MyProject
{
using System;
internal static class ODataConfig
{
public static void Configure(HttpConfiguration config, IUnityContainer container)
{
// Use Unity as WebAPI dependency resolver
config.DependencyResolver = new UnityDependencyResolver(container);
// Map OData Service
config.MapODataServiceDataObjectRoute(new DefaultDataObjectEdmModelBuilder(new[]
{
Assembly.Load("MyProject.Objects"),
typeof(ApplicationLog).Assembly,
typeof(UserSetting).Assembly,
typeof(FlexberryUserSetting).Assembly,
typeof(Lock).Assembly
}));
// Replace IHttpControllerActivator service
config.Services.Replace(typeof(IHttpControllerActivator), new ControllerActivator(container));
}
}
}
Теперь сервис, реализующий интерфейс IHttpControllerActivator
, может быть примерно следующим:
namespace IIS.MyProject
{
using System;
public class ControllerActivator : IHttpControllerActivator
{
private readonly IUnityContainer _container;
private readonly IHttpControllerActivator _defaultActivator;
public ControllerActivator(IUnityContainer container)
{
_container = container;
_defaultActivator = new DefaultHttpControllerActivator();
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
if (controllerDescriptor.ControllerName == "DataObject")
{
string dataServiceName = null;
switch (request.GetRouteData().Values["odataPath"])
{
case "ODataPathToMyObject":
case "ODataPathToMyOtherObject":
dataServiceName = "MSSQLDataService";
break;
default:
dataServiceName = "MongoDbDataService";
break;
}
ManagementToken token = request.GetODataServiceToken();
return new DataObjectController(_container.Resolve<IDataService>(dataServiceName), token.Model, token.Events, token.Functions);
}
return _defaultActivator.Create(request, controllerDescriptor, controllerType);
}
}
}
Исходный код этого примера можно найти в репозитории FlexberryOrmMongoDbDataServiceDemo.ODataBackend.