webapi net inyeccion injection dependency dependencias asp c# asp.net-core dependency-injection routing

c# - inyeccion - asp.net core Se inició una segunda operación en este contexto antes de que se completara una operación anterior



inyeccion de dependencias.net core (1)

Este problema está de hecho dentro de la ruta del middleware.

Por definición, un middleware es un singleton, por lo que una sola instancia maneja todas las solicitudes. Esto resulta en el estado de la instancia ( the IServiceConfig con the IServiceConfig conectado) al que se accede y cambia mediante múltiples solicitudes simultáneas; Es una cuestión clásica de concurrencia bien disimulada.

Un ejemplo.

La solicitud A ejecuta RouteAsync , establece el _serviceConfig y ejecuta una consulta en el DbContext . Nano segundos (o menos :)) más tarde, la solicitud B hace lo mismo. Mientras se ejecuta la consulta de la solicitud B, la solicitud A ejecuta GetVirtualPath , pero esta vez en el DbContext establecido por la solicitud B. Esto hace que se ejecute una segunda consulta en el DbContext de la solicitud B, que todavía tiene una en ejecución y aparece el error mencionado.

La solución es evitar el estado compartido, recuperando IServiceConfig al inicio de cada método.

Como ya ha dicho, no se puede inyectar esa dependencia a través del método Invoke ; El método Invoke no se ejecuta.

Aquí abajo está el RouteCustom reelaborado.

public class RouteCustom : IRouteCustom { private readonly IRouter _innerRouter; public RouteCustom(IRouter innerRouter) { _innerRouter = innerRouter ?? throw new ArgumentNullException(nameof(innerRouter)); } public async Task RouteAsync(RouteContext context) { var serviceConfig = context.HttpContext.RequestServices.GetRequiredService<IServiceConfig>(); // ... } public VirtualPathData GetVirtualPath(VirtualPathContext context) { var serviceConfig = context.HttpContext.RequestServices.GetRequiredService<IServiceConfig>(); // ... } }

Tengo una aplicación web ASP.Net Core 2.

Estoy intentando crear un middleware de enrutamiento personalizado, para poder obtener las rutas desde una base de datos.

En ConfigureServices tengo:

services.AddDbContext<DbContext>(options => options.UseMySQL(configuration.GetConnectionString("ConnectionClient"))); services.AddScoped<IServiceConfig, ServiceConfig>();

En Configurar:

app.UseMvc(routes => { routes.Routes.Add(new RouteCustom(routes.DefaultHandler); routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });

En el RouteCustom

public class RouteCustom : IRouteCustom { private readonly IRouter _innerRouter; private IServiceConfig _serviceConfig; public RouteCustom(IRouter innerRouter) { _innerRouter = innerRouter ?? throw new ArgumentNullException(nameof(innerRouter)); } public async Task RouteAsync(RouteContext context) { _serviceConfig = context.HttpContext.RequestServices.GetRequiredService<IServiceConfig>(); ... Operations inside _serviceConfig to get the route } public VirtualPathData GetVirtualPath(VirtualPathContext context) { _serviceConfig = context.HttpContext.RequestServices.GetRequiredService<IServiceConfig>(); ... Operations inside _serviceConfig to get the route } }

El IServiceConfig es solo una clase donde accedo a la base de datos para obtener datos, en este caso las rutas, pero también otros datos de configuración que necesito para la aplicación.

public interface IServiceConfig { Config GetConfig(); List<RouteWeb> SelRoutesWeb(); } public class ServiceConfig : IServiceConfig { private readonly IMemoryCache _memoryCache; private readonly IUnitOfWork _unitOfWork; private readonly IServiceTenant _serviceTenant; public ServiceConfig(IMemoryCache memoryCache, IUnitOfWork unitOfWork, IServiceTenant serviceTenant) { _memoryCache = memoryCache; _unitOfWork = unitOfWork; _serviceTenant = serviceTenant; } public Config GetConfig() { var cacheConfigTenant = Names.CacheConfig + _serviceTenant.GetId(); var config = _memoryCache.Get<Config>(cacheConfigTenant); if (config != null) return config; config = _unitOfWork.Config.Get(); _memoryCache.Set(cacheConfigTenant, config, new MemoryCacheEntryOptions() { SlidingExpiration = Names.CacheExpiration }); return config; } public List<RouteWeb> SelRoutesWeb() { var cacheRoutesWebTenant = Names.CacheRoutesWeb + _serviceTenant.GetId(); var routesWebList = _memoryCache.Get<List<RouteWeb>>(cacheRoutesWebTenant); if (routesWebList != null) return routesWebList; routesWebList = _unitOfWork.PageWeb.SelRoutesWeb(); _memoryCache.Set(cacheRoutesWebTenant, routesWebList, new MemoryCacheEntryOptions() { SlidingExpiration = Names.CacheExpiration }); return routesWebList; } }

El problema es que recibo este mensaje cuando pruebo con varias pestañas abiertas e intento actualizar todo al mismo tiempo: "Se inició una segunda operación en este contexto antes de que se completara una operación anterior"

Estoy seguro de que hay algo que estoy haciendo mal, pero no sé qué. Tiene que ser una mejor manera de acceder a la base de datos dentro del middleware de ruta personalizada o incluso una mejor manera de hacerlo.

Por ejemplo, en un Middleware regular (no en el de enrutamiento) puedo inyectar las dependencias a la función Invocar, pero no puedo inyectar dependencias aquí en RouteAsync o GetVirtualPath.

¿Qué puede estar pasando aquí?

Gracias por adelantado.

ACTUALIZACIÓN Estas son las excepciones que estoy recibiendo. Creo que están relacionados ...

An unhandled exception occurred while processing the request. InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe. Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection() Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+ExceptionInterceptor+EnumeratorExceptionInterceptor.MoveNext() System.Collections.Generic.List.AddEnumerable(IEnumerable<T> enumerable) System.Linq.Enumerable.ToList<TSource>(IEnumerable<TSource> source) MyProject.Repository.Repositories.PageWebRepository.SelRoutesWeb() in PageWebRepository.cs + return Context.PagesWebTrs.Include(p => p.PageWeb).Where(p => p.PageWeb.Active) MyProject.Web.AppControl.ServiceConfig.SelRoutesWeb() in ServiceConfig.cs + routesWebList = _unitOfWork.PageWeb.SelRoutesWeb(); MyProject.Web.AppConfig.RouteCustom.GetVirtualPath(VirtualPathContext context) in RouteCustom.cs + var routeWeb = _serviceConfig.SelRoutesWeb().FirstOrDefault(p => p.Area == routeInfo.Area && p.Controller == routeInfo.Controller && p.Action == routeInfo.Action && p.LanguageCode == routeInfo.Culture); Microsoft.AspNetCore.Routing.RouteCollection.GetVirtualPath(VirtualPathContext context, List<IRouter> routes) Microsoft.AspNetCore.Routing.RouteCollection.GetVirtualPath(VirtualPathContext context) Microsoft.AspNetCore.Mvc.Routing.UrlHelper.GetVirtualPathData(string routeName, RouteValueDictionary values) Microsoft.AspNetCore.Mvc.Routing.UrlHelper.Action(UrlActionContext actionContext) Microsoft.AspNetCore.Mvc.UrlHelperExtensions.Action(IUrlHelper helper, string action, string controller, object values, string protocol, string host, string fragment) Microsoft.AspNetCore.Mvc.UrlHelperExtensions.Action(IUrlHelper helper, string action, string controller, object values) Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GenerateForm(ViewContext viewContext, string actionName, string controllerName, object routeValues, string method, object htmlAttributes) Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGeneratorExtensions.GenerateForm(IHtmlGenerator generator, ViewContext viewContext, string actionName, string controllerName, string fragment, object routeValues, string method, object htmlAttributes) Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper.Process(TagHelperContext context, TagHelperOutput output) Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output) Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner+<RunAsync>d__0.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) AspNetCore._Views_Contents_NewsList_cshtml+<ExecuteAsync>d__21.MoveNext() in NewsList.cshtml + <h1>@Model.BasePage.PageTitle</h1> System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderPageCoreAsync>d__16.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderPageAsync>d__15.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderAsync>d__14.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor+<ExecuteAsync>d__22.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor+<ExecuteAsync>d__21.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.ViewResult+<ExecuteResultAsync>d__26.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeResultAsync>d__19.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResultFilterAsync>d__24.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) MyProject.Web.AppConfig.TenantMiddleware+<Invoke>d__3.MoveNext() in Tenant.cs + await _next.Invoke(httpContext); System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

Y éste:

An unhandled exception occurred while processing the request. MySqlException: There is already an open DataReader associated with this Connection which must be closed first. MySql.Data.MySqlClient.Interceptors.ExceptionInterceptor.Throw(Exception exception) Stack Query Cookies Headers MySqlException: There is already an open DataReader associated with this Connection which must be closed first. MySql.Data.MySqlClient.Interceptors.ExceptionInterceptor.Throw(Exception exception) MySql.Data.MySqlClient.MySqlCommand.Throw(Exception ex) MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) System.Data.Common.DbCommand.ExecuteReader() Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary<string, object> parameterValues) Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary<string, object> parameterValues) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+Enumerator.BufferlessMoveNext(bool buffer) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+Enumerator.MoveNext() Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.GetResult<TResult>(IEnumerable<ValueBuffer> valueBuffers, bool throwOnNullResult) lambda_method(Closure , QueryContext ) Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass17_1.<CompileQueryCore>b__0(QueryContext qc) System.Linq.Queryable.Count<TSource>(IQueryable<TSource> source) X.PagedList.PagedList..ctor(IQueryable<T> superset, int pageNumber, int pageSize) X.PagedList.PagedListExtensions.ToPagedList<T>(IEnumerable<T> superset, int pageNumber, int pageSize) MyProject.Repository.Repositories.LinkRepository.SelSearchWeb(string searchText, int pageNumber, int pageSize) in LinkRepository.cs + return Context.LinksTrs.Include(p => p.Link) MyProject.Web.Controllers.ContentsController.LinksList(LinksSearchModelWeb searchModel) in ContentsController.cs + var items = _unitOfWork.Link.SelSearchWeb(searchModel.SearchText, searchModel.PageNumber ?? 1, searchModel.PageSize ?? 10); lambda_method(Closure , object , Object[] ) Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(object target, Object[] parameters) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__12.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextActionFilterAsync>d__10.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeInnerFilterAsync>d__14.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) MyProject.Web.AppConfig.TenantMiddleware+<Invoke>d__3.MoveNext() in Tenant.cs + await _next.Invoke(httpContext); System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

Este es el UnitOfWork

public interface IUnitOfWork : IDisposable { ICompanyRepository Company { get; } IConfigRepository Config { get; } ... void Complete(); } public class UnitOfWork : IUnitOfWork { private readonly DbContext _context; public UnitOfWork(DbContext context) { _context = context; Company = new CompanyRepository(_context); Config = new ConfigRepository(_context); ... } public ICompanyRepository Company { get; private set; } public IConfigRepository Config { get; private set; } ... public void Complete() { _context.SaveChanges(); } public void Dispose() { _context.Dispose(); } }

ACTUALIZAR

Después de revisar los comentarios y hacer muchas pruebas, la mejor pista que tengo es que cuando elimino la línea CustomRoute, el problema desaparece. Eliminando esta línea de la función Configurar en Startup.cs

routes.Routes.Add(new RouteCustom(routes.DefaultHandler));

También he intentado eliminar, primero los métodos RouteAsync y luego GetVirtualPath, pero si alguno de ellos está presente, aparece un error, por lo que está claro que el problema está en esta clase CustomRoute.

En TenantMiddleware, que se llama primero para cualquier solicitud, estoy inyectando UnitOfWork y no tengo ningún problema. Este middleware se crea en la función Configurar:

app.UseMiddleware<TenantMiddleware>();

Y por dentro, estoy inyectando UnitOfWork y lo uso en cada solicitud, como esto:

Invocación pública de tareas asíncronas (HttpContext httpContext, IServiceTenant serviceTenant) {... realizando operaciones de base de datos para recuperar los datos del tenent.

} public class ServiceTenant : IServiceTenant { public ServiceTenant(IHttpContextAccessor contextAccessor, IMemoryCache memoryCache, IUnitOfWorkMaster unitOfWorkMaster) { _unitOfWorkMaster = unitOfWorkMaster; } ...performing DB operations }

Entonces, el problema con CustomROute es que no puedo inyectar las dependencias agregando a la función Invocar así:

public async Task Invoke(HttpContext httpContext, IServiceTenant serviceTenant)

Así que tengo que llamar al Servicio correspondiente (Dentro de ese servicio, inyecto el UnitOfWork y realizo las operaciones de DB) de esta manera, y creo que esto puede ser lo que está causando problemas:

public async Task RouteAsync(RouteContext context) { _serviceConfig = context.HttpContext.RequestServices.GetRequiredService<IServiceConfig>(); .... }

Debido a que esta es la única manera que conozco de "inyectar" IServiceConfig en RouteAsync y GetVirtualPath ...

Además, lo estoy haciendo en todos los controladores, ya que estoy usando un BaseCOntroller, por lo que decido cuáles son los servicios de inyección que uso ...

public class BaseWebController : Controller { private readonly IMemoryCache _memoryCache; private readonly IUnitOfWork _unitOfWork; private readonly IUnitOfWorkMaster _unitOfWorkMaster; private readonly IServiceConfig _serviceConfig; private readonly IServiceFiles _serviceFiles; private readonly IServiceFilesData _serviceFilesData; private readonly IServiceTenant _serviceTenant; public BaseWebController(IServiceProvider serviceProvider) { _memoryCache = serviceProvider.GetRequiredService<IMemoryCache>(); _unitOfWork = serviceProvider.GetRequiredService<IUnitOfWork>(); _unitOfWorkMaster = serviceProvider.GetRequiredService<IUnitOfWorkMaster>(); _serviceConfig = serviceProvider.GetRequiredService<IServiceConfig>(); _serviceFiles = serviceProvider.GetRequiredService<IServiceFiles>(); _serviceFilesData = serviceProvider.GetRequiredService<IServiceFilesData>(); _serviceTenant = serviceProvider.GetRequiredService<IServiceTenant>(); } ... }

Y luego, en cada controlador, en lugar de hacer referencia a todos los servicios inyectados, puedo hacerlo solo para aquellos que necesito, como esto:

public class HomeController : BaseWebController { private readonly IUnitOfWork _unitOfWork; public HomeController(IServiceProvider serviceProvider) : base(serviceProvider) { _unitOfWork = serviceProvider.GetRequiredService<IUnitOfWork>(); } public IActionResult Index() { ... } }

No sé si esto tiene algo que ver con mi problema, pero solo te estoy mostrando lo que creo que puede ser el problema, para que puedas tener más información.

Gracias.

ACTUALIZAR

Este es el código de la base de datos para recuperar las rutas:

public class PageWebRepository : Repository<PageWeb>, IPageWebRepository { public PageWebRepository(DbContext context) : base(context) { } public List<RouteWeb> SelRoutesWeb() { return Context.PagesWebTrs.Include(p => p.PageWeb).Where(p => p.PageWeb.Active) .Select(p => new RouteWeb { PageWebId = p.PageWebId, LanguageCode = p.LanguageCode, Route = p.Route, Regex = p.PageWeb.Regex.Replace("<route>", p.Route), Params = p.PageWeb.Params, Area = p.PageWeb.Area, Controller = p.PageWeb.Controller, Action = p.PageWeb.Action, Type = p.PageWeb.Type, Sidebar = p.PageWeb.Sidebar, BannerIsScript = p.PageWeb.BannerIsScript, Title = p.Title, Description = p.Description, Keywords = p.Keywords, ScriptHead = p.ScriptHead, ScriptBody = p.ScriptBody, BannerScript = p.BannerScript, BannerUrl = p.BannerUrl, }).ToList(); } }

Donde PagesWebTrs son las traducciones de las páginas (multilenguaje) y PagesWeb es la tabla principal.