How to do server side pre filtering with Entity Framework and Dynamic Data? - entity-framework

I use Entity Framework 4.0 and need to prefilter all queries using TennantId. I modified T4 template to add pre-filter to all ObjectSets like so and it works for "regular" part of the application.
public ObjectSet<Category> Categories
{
get
{
if ((_Categories == null))
{
_Categories = base.CreateObjectSet<Category>("Categories");
_Categories = _Categories.Where("it.TenantId = 10");
}
return _Categories;
}
}
The problem I have is that ASP.NET Dynamic Data doesn't invoke these methods and goes directly to CreateQuery which I cannot override.
Is there any way to prefilter data in this scenario?

You can set a condition for each entity in your Edm and EF will automatically append that condition in the "Where" clause of all the queries it generates.
See my answer to here that might help you.

Related

Entity Framework Core 1.0 CurrentValues.SetValues() does not exist

I'm attempting to update an entity and its related child entities using Entity Framework Core 1.0 RC 1, where the entities are detached from DbContext. I've done this previously using a solution similar to the one described in this answer.
However, it seems that we are no longer able to do the following using Entity Framework 7:
DbContext.Entry(existingPhoneNumber).CurrentValues.SetValues();
Visual Studio complains that:
EntityEntry does not contain a definition for 'CurrentValues'
etc...
I presume this means that this has not (yet?) been implemented for EF Core 1.0? Apart from manually updating the properties, is there any other solution?
As you have noticed, this API is not implemented yet in EF Core. See this work item: https://github.com/aspnet/EntityFramework/issues/1200
I know this is an old question but I ran into this issue today, and it appears it still isn't implemented in EF Core. So I wrote an extension method to use in the meantime that will update any object's properties with the matching values of any other object.
public static class EFUpdateProperties
{
public static TOrig UpdateProperties<TOrig, TDTO>(this TOrig original, TDTO dto)
{
var origProps = typeof(TOrig).GetProperties();
var dtoProps = typeof(TDTO).GetProperties();
foreach(PropertyInfo dtoProp in dtoProps)
{
origProps
.Where(origProp => origProp.Name == dtoProp.Name)
.Single()
.SetMethod.Invoke(original, new Object[]
{
dtoProp.GetMethod.Invoke(dto, null) });
}
);
return original;
}
}
Usage:
public async Task UpdateEntity(EditViewModel editDto)
{
// Get entry from context
var entry = await _context.Items.Where(p => p.ID == editDto.Id).FirstOrDefaultAsync();
// Update properties
entry.UpdateProperties(editDto);
// Save Changes
await _context.SaveChangesAsync();
}

.net WebApi IQueryable EF

I'm using .net web Api with Entity Framework. Its really nice that you can just do
[EnableQuery]
public IQueryable<Dtos.MyDto> Get()
{
return dbContext.MyEntity.Select(m => new MyDto
{
Name = m.Name
});
}
And you get odata applying to the Iqueryable, note also returning a projected dto.
But that select is a expression and so its being turned to into sql. Now in the above case that's fine. But what if I need to do some "complex" formatting on the return dto, its going to start having issues as SQL wont be able to do it.
Is it possible to create an IQueryable Wrapper?
QWrapper<TEntity,TDo>(dbcontext.MyEntity, Func<TEntity,TDo> dtoCreator)
it implements IQueryable so we still return it allowing webapi to apply any odata but the Func gets called once EF completes thus allowing 'any' .net code to be called as its not converting to SQL.
I don't want to do dbContext.MyEntity.ToList().Select(...).ToQueryable() or whatever as that will always return the entire table from the db.
Thoughts?
since you query already returns the data you expected, how about adding .Select(s=>new MyEntity(){ Name=s.Name }) for returning them as OData response? like:
return dbContext.MyEntity.Select(m => new MyDto
{
Name = m.Name
}).Select(s=>new MyEntity(){ Name=s.Name });

Updating multiple records using Entity Framework

I am using Entity Framework 5. I am looking for a better approach to update multiple records.
People are talking about EF Extensions. But I am not sure how to use it with my scenario.
This is my method signature.
internal void Update( List<Models.StockItem> stockItemsUpdate)
I need to update all the corresponding stockitem entities.
using (var context = new eCommerceEntities())
{
var items = context.StockItems.Where(si => stockItemsUpdate.Select(it => it.ID).Contains(si.ID));
}
I believe above query will return those entities.
How can I use EF extensions in this scenario?
Thanks.
In EntityFramework.Extended's BatchExtensions there is an Update extension method with this signature:
public static int Update<TEntity>(
this IQueryable<TEntity> source,
Expression<Func<TEntity, TEntity>> updateExpression)
You can use this as follows:
items.Update(item => new StockItem { Stock = 0 });
to set the stock of the selected items to 0.

Entity Framework using Generic Predicates

I use DTO's to map between my Business and Entity Framework layer via the Repository Pattern.
A Standard call would look like
public IClassDTO Fetch(Guid id)
{
var query = from s in _db.Base.OfType<Class>()
where s.ID == id
select s;
return query.First();
}
Now I wish to pass in filtering criteria from the business layer so I tried
public IEnumerable<IClassDTO> FetchAll(ISpecification<IClassDTO> whereclause)
{
var query = _db.Base.OfType<Class>()
.AsExpandable()
.Where(whereclause.EvalPredicate);
return query.ToList().Cast<IClassDTO>();
}
The Call from the business layer would be something like
Specification<IClassDTO> school =
new Specification<IClassDTO>(s => s.School.ID == _schoolGuid);
IEnumerable<IClassDTO> testclasses = _db.FetchAll(school);
The problem I am having is that the .Where clause on the EF query cannot be inferred from the usage. If I use concrete types in the Expression then it works find but I do not want to expose my business layer to EF directly.
Try making FetchAll into a generic on a class instead, like this:-
public IEnumerable<T> FetchAll<T> (Expression<Func<T,bool>> wherePredicate)
where T:IClassDTO //not actually needed
{
var query = _db.Base.OfType<T>()
.AsExpandable()
.Where(wherePredicate);
return query;
}
pass in school.Evalpredicate instead. FetchAll doesn't appear to need to know about the whole specification, it just needs the predicate, right? If you need to cast it to IClassDTO, do that after you have the results in a List.

Entity Framework IQueryable

I'm having problems querying the entity model to get additional information.
My db has a Program table with a one to many relation with an Events table. The Entity model generates the relationships just fine, but I'm unable to figure out how to query the model to get the progam object with its events.
I can do this:
var foo = from program in entities.ProgramSet
where program.StartDate > DateTime.now
orderby program.StartDate
select program;
No problems there. From what I've found on Microsofts Page (Shaping queries with Entity framework): msdn.microsoft.com/en-us/library/bb896272.aspx, if I wanted to get the child objects, I just do the following:
// Define a LINQ query with a path that returns
// orders and items for a contact.
var contacts = (from contact in context.Contact
.Include("SalesOrderHeader.SalesOrderDetail")
select contact).FirstOrDefault();
However, there is no .Include or Include that I can find on the query.
Any suggestion? I know that I can do a foreach across the results, then run a .Events.Load() on it, but doesn't that force the IQueriable result to execute the sql, instead of optomize it to run only when a .ToList() etc is called on it?
Here is some sample code from my project:
public class ProgramRepository : CT.Models.IProgramRepository
{
CTEntities db = new CTEntities();
public IQueryable<Program> FindAllPrograms()
{
return db.ProgramSet;
}
public IQueryable<Program> FindUpcomingPrograms()
{
var programs = from program in FindAllPrograms()
where program.StartDate > DateTime.Now
orderby program.StartDate
select program;
return programs;
}
With the FindUpComingPrograms I would like to have it also include the Events Data. There is a relationship between the Program and Events model. Program has a List<Events> property, that I would like to fill and return with the IQueryable method.
Thanks again!
The Include Function is part of the ObjectQuery object...
I think you are going to need to re-write your query to look something like this:
var contacts = context.Contact.Include("SalesOrderHeader.SalesOrderDetail").FirstOrDefault();
//Not sure on your dot path you might have to debug that a bit
Here is an Article that has some examples...