So I'm using Entity Framework Code First (so no .edmx)
I have a base entity class with a bool IsEnabled to do soft delete's
I am using repository pattern so all queries against the repository can be filtered out with IsEnabled.
However any time I use the repository to get an MyType which is IsEnabled, Lazy Loading MyType.Items may mean that Items could be not enabled.
Is there a way, perhaps with EF Fluent to describe how to do filtering on tables?
Update:
If I have a Dbset
public class UnitOfWork : DbContext
{
private IDbSet<MyObj> _MyObj;
public IDbSet<MyObj> MyObjs
{
get { return _MyObj ?? (_MyObj = base.Set<MyObj>()); }
}
}
Is there any way I can tell the DbContext to filter the DbSet?
No, there is no way to define a filter for lazy loading (also not for eager loading using Include). If you want that your navigation collections only get populated with items where IsEnabled is true you can only shape your queries accordingly, for example with explicit loading:
context.Entry(parent).Collection(p => p.Items).Query()
.Where(i => i.IsEnabled)
.Load();
This will populate the Items collection of parent only with the enabled items.
Edit
I feel a bit like the messenger of the bad news about a lost battle who gets his head knocked off. Maybe it's too hard to believe that Entity Framework sometimes does not have the capabilities you want. To improve my chance to convince you I add a quote from an authority, Julie Lerman:
Neither eager loading nor deferred/lazy loading in the Entity
Framework allows you to filter or sort the related data being
returned.
It looks like it is still possible. If you are intrested you can take a look at the Wiktor Zychla blogpost, where he gives a solution to the soft delete problem.
This http://blogs.claritycon.com/blog/2012/01/25/a-smarter-infrastructure-automatically-filtering-an-ef-4-1-dbset/ basically defines how I can achieve what I was looking for.
Basically you create a FilteredDbSet and make all your DbContext IDbSet's return it.
Related
My project uses Entity Framework Core as ORM. Lazy loading is enabled by default:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies();
}
I need to write a code, which processes some big collection of objects with navigation properties. To decrease amount of database requests, I would like to download the objects with their navigation properties "eagerly".
What is right way to do this? Can I just use something like this:
dbContext.MyObjects.Include(myObject => myObject.NavigationProperty).ToListAsync()
Yes, Include forces the EF to load the data for the given property within the query.
You might also consider to use .ToListAsync() overload and await the call. It might help the thread to not freeze while loading a huge result set from the database.
Doco with examples can be found here: https://learn.microsoft.com/en-us/ef/core/querying/related-data/eager
Entity Framework Layer Guidance
I'm in the design stage of a WPF business application. The first stage of this application will be a WPF/Desktop application. Later iterations may include a browser based mini version.
I envision creating a dll or 2 that contain the domain model & dbcontext that all applications(Desktop or Browser) will use.
My intention is to ride or die with EF. I'm not worried about using DI/Repository patterns etc for flexibility. The benefits of using them don't outweigh the added complexity in my opinion for this project. My plan is to use a model, and a derived dbcontext.
Having said that, I'm looking for input on where to put certain types of method code.
An example will hopefully make my question more clear:
Let's say I have the following two entities..
Entity: Employee
Entity: PermissionToken
Inside of these two entities I have a ManyToMany relationship resulting in me creating another entity for the relationship:
EmployeesPermissionTokens
For clarity, the PermissionToken Entity's Primary Key is an Enum representing the permission..
In the application, lets say the current user is Administering Employees and wants to grant a permission to an Employee.
In the app, I could certainly code this as:
var e = dbcontext.Employees.Find(1);
var pt = new PermissionToken
{
PermissionID=PermissionTypeEnum.DELETEUSER";
...
}
e.PermissionTokens.Add(pt)
But it seems to me that it would be more convenient to wrap that code in a method so that one line of code could perform those actions from whatever application chooses to do so. Where would a method like that live in all of this?
I've thought about adding a static method to the EF Entity:
In The employee class:
public static void GrantPermission(PermissionToken token)
{
e.PermissionTokens.Add(token);
}
Going further, what would be really convenient for the app would be the ability to write a line like this:
Permissions.GrantToEmployee(EmployeeID employeeId, PermissionTypeEnum
permissionId);
Of course that means that the method would have to be able to access the DbContext to grab the Employee Object and the PermissionObject by ID to do its work. I really want to avoid my entities knowing about/calling DbContext because I feel long term the entities get stuffed full of dbcontext code which in my opinion shouldn't even be in the Model classes.
So Where would a method like this go?
My gut tells me to put these sorts of code in my derived DbContext since in order to do these sorts of things, the method is going to need access to a DbContext anyway.
Does this make sense, or am I missing something? I hate to write oodles of code and then figure out 3 months later that I went down the wrong road to start with. Where should these types of methods live? I know there is probably a purist answer to this, but I'm looking for a clean, real world solution.
First of all you are making a good decision to not abstract EF behind a repository.
With the EF Context you have a class supporting the Unit Of Work pattern which is handling your data access needs.No need to wrap it up in repository.
However this does not mean you should call the Context directly from your controller or viewmodel.
You could indeed just extend the DbContext however I suggest to use services to mediate between your controllers/view models and your dbcontext.
If e.g. in your controller you are handling a user request (e.g. the user has clicked a button) then your controller should call a service to archive what ever "Use Case" is behind the button.
In your case this could be a PermissionService, the PermissionService would be the storage for all operations concerning permission.
public class PermissionService
{
PermissionService(DbContext context)
{
}
public bool AddPermission(Employee e, PermissionType type) { }
public bool RemovePermission(Employee e, PermissionType type) {}
}
Your service ofcourse needs access to the DbContext.
It makes sense to use DI here and register the DbContext with a DI Container.
Thus the context will be injected into all your services. This is pretty straight forward and I do not see any extra complexity here.
However, if you don't want to do this you can simply new up up the Db Context inside your services. Of course this is harder / impossible to mock for testing.
I'm sorry if my question is normal. But I meet this problem when I design my ASP.NET MVC 4.0 Application using Entity Framework 5.
If I choose Eager Loading, I just simplify using :
public Problem getProblemById(int id) {
using(DBEntity ctx = new DBEntity ())
{
return (Problem) ctx.Posts.Find(id);
}
}
But if I use Eager Loading, I will meet problem: when I want to navigate through all its attributes such as comments (of problem), User (of Problem) ... I must manually use Include to include those properties. and At sometimes, If I don't use those properties, I will lost performance, and maybe I lost the strength of Entity Framework.
If I use Lazy Loading. There are two ways to use DBContext object. First way is using DBContext object locally :
public Problem getProblemById(int id) {
DBEntity ctx = new DBEntity ();
return (Problem) ctx.Posts.Find(id);
}
Using this, I think will meet memory leak, because ctx will never dispose again.
Second way is make DBContext object static and use it globally :
static DBEntity ctx = new DBEntity ();
public Problem getProblemById(int id) {
return (Problem) ctx.Posts.Find(id);
}
I read some blog, they say that, if I use this way, I must control concurrency access (because multi request sends to server) by myself, OMG. For example this link :
Entity Framework DBContext Usage
So, how can design my app, please help me figure out.
Thanks :)
Don't use a static DBContext object. See c# working with Entity Framework in a multi threaded server
A simple rule for ASP.Net MVC: use a DBContext instance per user request.
As for using lazy loading or not, I would say it depends, but personally I would deactivate lazy-loading. IMO it's a broken feature because there are fundamental issues with it:
just too hard to handle exceptions, because a SQL request can fail at any place in your code (not just in the DAL because one developer can access to a navigation property in any piece of code)
poor performances if not well used
too easy to write broken code that produces thousands of SQL requests
I'm doing a small practice project to improve my unit testing skills. I'm using Entity Framework Code First.
I'm using a FakeDBSet, which works well for simple lists of entities. When entity trees are returned things aren't so nice. In particular two way relationships aren't maintained as this is part of the Entity Framework magic.
I have two classes:
public class Book
{
public virtual ICollection<Review> Reviews {get; set;}
}
public class Review
{
public virtual Book Book { get; set;}
}
If I set the book for a review, the review does not get added to the book's review collection. It does when using EF, but not in my fake version.
Is there a way mock this behaviour, or should I not rely on EF to implement two way relationships? Or is mocking the data context just a waste of time?
This is actually a pretty common problem (and one without a really good answer). There is a process which happens inside of EF called fixups which runs inside the detect changes loop (the one that triggers on add/remove and a few other changes). This evaluates backlinks in your model. When you start mocking your context you are going to lose that detect changes loop and hence the fixups.
In the past I've gotten around this by understanding this particular limitation of my mocks and making sure i do my setup code in the correct way to make sense in the code (which lets face it is pretty un-ideal). The other option here is to go to some form of real lightweight database in your unit tests and keep using EF.
A possible solution I've found is to create a mock object that mimics the EF fixup code.
Here is an example using the Mocking framework NSubstitute:
private static Book CreateMockBook()
{
var book = Substitute.For<Book>();
// Mock EF fixup: Add a review to collection should also set book for the review
book.Reviews.Add(Arg.Do<Review>((x) => { if(x.Book != book) x.Book = book; }));
return book;
}
private static Review CreateMockReview()
{
var review = Substitute.For<Review>();
// Mock EF fixup: Set a book for the review should also should add the review to book's review collection
review.When(x => x.Book = Arg.Any<Book>()).Do(x => review.Book.Review.Add(review));
return review;
}
This works quite nicely, but I'm not sure if needing to mock this behaviour is an indication that my tests have got too complicated or that my code is making use of side effects that it shouldn't.
I'd be interested in what other people think of this?
Im writing an web application with MVC using Entity Framework for my backend logic. My problem is that I have an entity that has certain fields that should never be changed on an update. I am not really sure what the best way to solve this problem would be. There is going to be a lot of data processed in my application, so I cant afford to just hack up a solution.
Is it possible to just define the fields as readonly in the POCO entities ? Or should I write and entity framework extension class that validates all updates. Could it be done in the mapping files between EF and the actual database?
I am relatively new with EF, so I hope some of you might be able to give me some pointers!
Thanks!
If you are using .NET 4.5 and EF 5 (i.e. MVC 4), you can simply set IsModified = false on the individual properties in question. This has the benefit of sticking close to the default out-of-the-box MVC conventions.
For example, if you have a CreatedBy field that shouldn't be touched when the record is updated, use the following in your controller:
[HttpPost]
public ActionResult Edit(Response response)
{
if (ModelState.IsValid)
{
db.Entry(response).State = EntityState.Modified;
db.Entry(response).Property(p => p.CreatedBy).IsModified = false;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(response);
}
Note that the IsModified line is the only change from the default controller action.
You MUST put this line AFTER setting .State = EntityState.Modified (which applies to the record as a whole and adds the record into the db context).
The effect is that EF will not include this column in the SQL UPDATE statement.
I am still (very) shocked that there are no [InsertOnly] or [UpdateOnly] attributes similar to [ReadOnly]. This seems like a major oversight by the MVC team. Am I missing something?
I'm not fully satisfied with this solution because it's a hack: You're telling EF that no change was made when what you really mean to say is "HANDS OFF". It also means that you have to use this code anyplace where the field could be updated. It would be better to have an attribute on the class property.
(Apologies for posting to an older thread, but I've not see this solution anywhere else. ViewModels are robust but a lot of work, and EF was supposed to make things easier, not harder...)
Well I would advice against ever using the EF classes in the View. You're best bet is to construct ViewModel classes and use Automapper to map them from the EF classes.
When you are updating records in the database though, you can control which fields in the ViewModel are used to update the existing fields in the EF class.
The normal process would be:
Use the Id to get the latest version of the existing object out of the database.
If you are using optimistic concurrency control then check that the object has not been updated since the ViewModel was created (so check timestamp for example).
Update this object with the required fields from your ViewModel object.
Persist the updated object back to the database.
Update to include Automapper examples:
Let's say your POCO is
public class MyObject
{
public int Id {get;set;}
public string Field1 {get;set;}
public string Field2 {get;set;}
}
and Field1 is the field you don't want updating.
You should declare a view model with the same properties:
public class MyObjectModel
{
public int Id {get;set;}
public string Field1 {get;set;}
public string Field2 {get;set;}
}
and Automap between them in the constructor of your Controller.
Mapper.CreateMap<MyObject, MyObjectModel>();
you can if you wish (although I prefer to do this manually, automap the other way too:
Mapper.CreateMap<MyObjectModel, MyObject>().ForMember(dest=>dest.Field1, opt=>opt.Ignore());
When you are sending date to your website you would use:
var myObjectModelInstance = Mapper.Map<MyObject, MyObjectModel>(myObjectInstance);
to create the viewModel.
When saving the data, you'd probably want something like:
public JsonResult SaveMyObject(MyObjectModel myModel)
{
var poco = Mapper.Map<MyObjectModel, MyObject>(myModel);
if(myModel.Id == 0 )
{
//New object
poco.Field1 = myModel.Field1 //set Field1 for new creates only
}
}
although I'd probably remove the exclusion of Field1 above and do something like:
public JsonResult SaveMyObject(MyObjectModel myModel)
{
var poco;
if(myModel.Id == 0)
{
poco = Mapper.Map<MyObjectModel, MyObject>(myModel);
}
else
{
poco = myDataLayer.GetMyObjectById(myModel.Id);
poco.Field2 = myModel.Field2;
}
myDataLayer.SaveMyObject(poco);
}
note I believe that best-practise would have you never Automap FROM the ViewModel, but to always do this manually, including for new items.
I just asked a very similar question, and I believe the answer to that one may help out a lot of folks who stumble across this one as well. The OP mentions that these are fields that should never change, and using PropertySaveBehavior.Ignore ensures this. With the existing answers to this question, you need to make custom save methods or introduce mapping where it might not make sense. By setting the AfterSave property behavior instead, you can prevent this from being possible in EF altogether.
In my project, I am generically accessing a property that is on an abstract class so I have to set it like this:
MyProperty.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
If you're accessing it directly on a known class, you'd use this:
...
.Property(e => e.YourProperty)
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);