I need to create a wrapper for ObjectSet
to be able to create a centralized access control.
The goal is to implement the CA without making changes to queries already in the system, which in this case are scattered throughout the code (there is no centralized layer for data access).
The connection to the bank uses ObjectContext
.
The wrapper of ObjectSet
is created, this is:
public class ObjectSetWrapper<TEntity> : IQueryable<TEntity> where TEntity : EntityObject
{
private IQueryable<TEntity> QueryableModel;
private ObjectSet<TEntity> ObjectSet;
public ObjectSetWrapper(ObjectSet<TEntity> objectSetModels)
{
this.QueryableModel = objectSetModels;
this.ObjectSet = objectSetModels;
}
public ObjectQuery<TEntity> Include(string path)
{
return this.ObjectSet.Include(path);
}
public void DeleteObject(TEntity @object)
{
this.ObjectSet.DeleteObject(@object);
}
public void AddObject(TEntity @object)
{
this.ObjectSet.AddObject(@object);
}
public IEnumerator<TEntity> GetEnumerator()
{
return QueryableModel.GetEnumerator();
}
public Type ElementType
{
get { return typeof(TEntity); }
}
public System.Linq.Expressions.Expression Expression
{
get { return this.QueryableModel.Expression; }
}
public IQueryProvider Provider
{
get { return this.QueryableModel.Provider; }
}
public void Attach(TEntity entity)
{
this.ObjectSet.Attach(entity);
}
public void Detach(TEntity entity)
{
this.ObjectSet.Detach(entity);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.QueryableModel.GetEnumerator();
}
}
It is not of type ObjectSet
, but this is not important, it only needs to be used in queries LinqToEntities
. And it even works for simple queries like this:
//db.Produto é do tipo ObjectSetWrapper<Produto >
var query = (from item in db.Produto where item.Quantidade > 0 select new { item.Id, item.Nome, item.Valor });
var itensList = query.Take(10).ToList();
But when there is a * subquery *, like this:
//db.Produto é do tipo ObjectSetWrapper<Produto>
var query = (from item in db.Produto
select new
{
Id = item.Id,
Nome = item.Nome,
QuantidadeVendas = (from venda in db.Venda where venda.IdProduto == item.Id select venda.Id).Count()
}).OrderByDescending(x => x.QuantidadeVendas);
var productsList = query.Take(10).ToList();
I get a NotSupportedException
, stating that it is not possible to create a constant of my subquery entity type (in this case, Venda
):
How do I make this query work? I do not need the wrapper to be of typeUnable to create a constant value of type 'MyNamespace.Model.Venda'. Only primitive types or enumeration types are supported in this context.
ObjectSet
, only that it can be used in queries, keeping queries of the system running.
Updated
Update the ObjectSetWrapper class to implement IObjectSet<TEntity>
as indicated by Miguel Angelo, but the errors continue. Now the class has this signature:
public class ObjectSetWrapper<TEntity> : IObjectSet<TEntity>, IQueryable<TEntity> where TEntity : EntityObject
To reinforce, the wrapper idea is to be able to perform access control checks on query queries, so it is important to keep queries with linq to entities already in place on the system.