How to intercept a SELECT query - entity-framework

I am exploring Entity Framework 7 and I would like to know if there is a way to intercept a "SELECT" query. Every time an entity is created, updated or deleted I stamp the entity with the current date and time.
SELECT *
FROM MyTable
WHERE DeletedOn IS NOT NULL
I would like all my SELECT queries to exclude deleted data (see WHERE clause above). Is there a way to do that using Entity Framework 7?

I am not sure what your underlying infrastructure looks like and if you have any abstraction between your application and Entity Framework. Let's assume you are working with DbSet<T> you could write an extension method to exclude data that has been deleted.
public class BaseEntity
{
public DateTime? DeletedOn { get; set; }
}
public static class EfExtensions
{
public static IQueryable<T> ExcludeDeleted<T>(this IDbSet<T> dbSet)
where T : BaseEntity
{
return dbSet.Where(e => e.DeletedOn == null);
}
}
//Usage
context.Set<BaseEntity>().ExcludeDeleted().Where(...additional where clause).

I have somewhat same issue. I'm trying to intercept read queries like; select, where etc in order to look into the returned result set. In EF Core you don't have an equivalent to override SaveChanges for read queries, unfortunately.
You can however, still i Entity Framework Core, hook into commandExecuting and commandExecuted, by using
var listener = _context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandListener());
and creating a class with following two methods
public class CommandListener
{
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
{
//do stuff.
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
public void OnCommandExecuted(object result, bool async)
{
//do stuff.
}
}
However these are high lewel interceptors and hence you won't be able to view the returned result set (making it useless in your case).
I recommend two things, first go to and cast a vote on the implementation of "Hooks to intercept and modify queries on the fly at high and low level" at: https://data.uservoice.com/forums/72025-entity-framework-core-feature-suggestions/suggestions/1051569-hooks-to-intercept-and-modify-queries-on-the-fly-a
Second you can use PostSharp (a commercial product) by using interceptors like; LocationInterceptionAspect on properties or OnMethodBoundaryAspect for methods.

Related

How to get navigation property of foreign key when calling SaveChanges()?

I'm using EF5 code first.
We have a method
LogHistoryTracking(DbEntityEntry entity)
to log changes when SaveChanges is called.
At SaveChanges, we get the changed entities and pass into LogHistoryTracking
var changedEntities = ChangeTracker.Entries().ToList();
But when I access
changedEntity.OriginalValues.PropertyNames
there is no properties for foreign keys object (only foreign key Id - but how can we get the data when there is only id here?).
I also tried to google for a solution, but this issue might be not so popular.
There is this article, but it does not work.
Appreciate any help. Thanks.
If you want to have your entity properties to be accessible you must 'Include' them prior to accessing them. Like in the following example which gets the orders of the first cutomer :
var orders = context.Customers
.Include("Orders")
.First().Orders;
In this example if you do not call .Include("Orders") you will not have Customer.Orders. The same goes if you have foreign key and forget to include the navigation property of the foreign key. This is because the key (the ID) is part of the object and the navigation property is not.
Let us see one real world example :
public class Employee : Entity
{
public virtual int CompanyUserId { get; set; }
public virtual CompanyUser CompanyUser { get; set; }
//... cut out for brevity
}
If you get the employees like this :
var employees = context.Employees;
You will not be able to access employees[0].CompanyUser after
context.SaveChanges() because of lazy loading. The connection is disposed after context.SaveChanges(), so no more data fetching.
But if you call :
var employees = context.Employees
.Include("CompanyUser")
.ToArray();
You will be able to access employees[0].CompanyUser.SomeProperty right away before context.SaveChanges regardless lazy loading because ToArray() will execute the query and fetch the entities with the "includes".
If you call :
var employees = context.Employees
.Include("CompanyUser");
Then you will have employee[0].CompanyUser.SomeProperty even after context.SaveChanges() with Lazy Loading because you have told EF to include "CompanyUser" property before executing the query. On execution EF will include the named property.
UPDATE
Intercepting DbContext can be done in at least two different ways.
First - override SaveChanges() or SaveChangesAsync because it is virtual:
public class MyDbContext : DbContext
{
public event Action<MyDbContext> SavingChanges = _ => { };
public override int SaveChanges()
{
this.SavingChanges(this);
return base.SaveChanges();
}
}
Second way without direct override is by hiding the DbContext inside interface like this one (this is from real project) :
public interface IUnitOfWork : IDisposable
{
void Commit();
}
Third way (somewhat different) is by intercepting the Db calls.
Fourth way exists but it depends on what IoC you use. If you use Castle Windsor you can use interceptors. I suppose that with every IoC there is its own way of intercepting this.

Create an Updatable Model - Entity Framework

I just want to know if there's a way on how to create an Updatable model. Right now, I have to create procedures for insert, update, and delete for all of the tables in my model. This is very tedious so I was wondering if there is one way which I could do to resolve this?
I remember before in my previous work that we used to make models and access them (CRUD) without creating procedures. But i'm not really certain now on how it was made.
Thank you!
There are various ways in which you can automate the generation (on the fly or already generated at compile time) of the actual SQL calls to the database to insert, select, update and delete within the Entity Framework.
You can use the ORM tools (e.g. Linq to Entities) to minimise or eliminate the writing of raw SQL. This means you still have to use the correct attributes on your entities and the properties/methods therein and that's a manual process. (Some backgrounding on this MSDN page)
You can allow the framework to automatically generate your entities based on some existing database schema (only possible with SqlServer-type databases) which basically does 90% of the work for you. There may be some cases where you need to override, for example, the default insert SQL with something custom. This is achieved via the Generate Database Wizard (which I think is a part of Visual Studio 2008+).
You can use POCO classes with EF. If you're using 4.1 and above, you can use the DbContext class. To map your model to the table / columns, simply override OnModelCreating in your context class (which inherits from DbContext). Say you have a model called User, a table called Users, and the context class MyContext, the code could be smth like this:
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
}
public class MyContext : DbContext
{
public MyContext() :
base("MyContext")
{
}
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().
.ToTable("Users");
modelBuilder.Entity<User>().
.Property(d => d.UserId)
.HasColumnName("UserId")
modelBuilder.Entity<User>().
.Property(d => d.UserName)
.HasColumnName("UserName");
}
}
To use it, simply add the User instance to your DbSet, then call SaveChanges:
using(MyContext ctx = new MyContext())
{
var u = new User() { UserId = 1, UserName = "A" };
ctx.Users.Add(u);
ctx.SaveChanges();
}

Can I write a generic repository with the db first scenario to dynamically get me an entity by id?

I'd like to know how to create a method that will allow me to generically do this...
public class Repo<T> : IGenericRepo<T> where T : class
{
protected PteDotNetEntities db;
public T Get(int id)
{
//how do I dynamically get to the correct entity object and select it by
//id?
}
}
Yes you can. If you know that all your entities will have simple primary key property of type int and name Id you can do simply this:
public interface IEntity
{
int Id { get; }
}
All your entities must implement this interface. Next you can simply do:
public class Repo<T> : IGenericRepo<T> where T : class, IEntity
{
protected PteDotNetEntities db;
public T Get(int id)
{
return db.CreateObjectSet<T>().FirstOrDefault(e => e.Id == id);
}
}
This is the simplest possible solution. There are better solutions using GetObjectByKey but they are more complex. The difference between FirstOrDefault and GetObjectByKey is repeatable execution. FirstOrDefault always executes DB query whereas GetObjectByKey first checks if the entity with the same key was already loaded / attached to the context and returns it without querying the database. As reference for version using GetObjectByKey you can check similar questions:
Entity Framework Simple Generic GetByID but has differents PK Name
Generic GetById for complex PK
You can simplify those examples if you know the name of the key property upfront (forced by the interface).
In case of using code first / DbContext API you can also check this question:
Generic repository EF4 CTP5 getById

Generic repository implementation with EF

For a simple repository
public interface ISimpleRepository<T>
{
IApplicationState AppState { get; set; }
void Add(T instance);
void Delete(T instance);
void Delete(Guid rowGuid);
IQueryable<T> GetAll();
T Load(Guid rowGuid);
void SaveChanges();
void Update(T instance);
}
my implementation of the Load() method for specific repository for class Product might look like this:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
Now this is assumed when my repository implementation class looks like this:
public class EntityFrameworkProductsProvider : IRepository<Product> ...
What if I had like dozens or hundreds of this small and simple entities that would all use the same behaviour when doing CRUDs (use the same implementation of methods)? I certainly don't want to go and create a class to implement IRepository for each one of them..
I want something like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
but I don't know how to implement the LINQ Select expression then because of course I can't write from e in _ctx.T where e... or do I?
I haven't run into this scenario yet because so far I only had very specific entities with custom repository implementation.
Because you tagged your question with entity-framework and entity-framework-4 I assume you are using ObjectContext API. ObjectContext offers method CreateObjectSet<T> which is equivalent of Set<T> on DbContext.
This question is actually duplicate of either:
Generic GetById with DbContext
Generic GetById with ObjectContext
Instead of writing _ctx.Products, you can write _ctx.Set<T>. That takes care of half of the problem (you need to add a generic constraint where T: class to your repository)
Then, if rowid is the object's key, you can use _ctx.Set<T>.Find(rowid) instead of a LINQ query to retrieve by Id.
Alternatively, you can create a base interface IHaveId (or a BaseEntity class, whatever you like) which has the Id property, and then add that as an generic constraint on T, so you can use it in your queries.
If you're using EF 4.1, see the sample generic repository here:
http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
I know that this is possible in EF4.1 with the DbContext API, where you have a "Set" method on the context that gets you the entity set corresponding to the type T. this way, you could have your repository like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
one more remark: I think you could use this syntax :
return _ctx.Products.FirstOrDefault(c=>c.id == rowid);
to get the entity you want instead of using the (from... in...). it's clearer (in my opinion) :)
Hope this helps

WCF with Entity Framework Error

Error: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I am trying to create a WCF service with Entity Framework (VS 2010, .NET 4). When I run it, I get the above error.
I read something about editing the T4 template, but it appears that it already has
[DataContractAttribute(IsReference=true)]
public partial class Person : EntityObject
and
[DataMemberAttribute()]
public global::System.Int32 ID
{
get
{
return _ID;
}
I am not sure what the difference is between
[DataMemberAttribute()] and [DataMember]
or
[DataContractAttribute(IsReference=true)] and [DataContract]
either.
public Person GetPersonByID(int id)
{
using (var ctx = new MyEntities())
{
return (from p in ctx.Person
where p.ID == id
select p).FirstOrDefault();
}
}
How does WCF and EF work together, properly?
Do you have navigation properties in your Person class? Did you disable lazy loading? Otherwise it will probably try to load content for navigation properties during serialization and it fails because of closed context.
To your other questions:
[DataMemberAttribute()] and [DataMember] are same. It is just shorter name.
[DataContractAttribute(IsReference=true)] and [DataContract] are not same. IsRefrence allows tracking circular references in navigation properties. Without this parameter circular reference causes never ending recursion.