How to get dbsets metadata from EF CodeFirst DbContext? - ef-code-first

How do you programatically get the metadata for the dbset classes from an EF CodeFirst dbcontext? This is to loop through for code generation purposes.

After some additional research, I think I found an answer. Basically, you have to drop down into the ObjectContext, the original EF context that DbContext is a wrapper for, and use the MetadataWorkspace information below.
Please add another answer if there is a direct way to get this directly from the DbContext as it would be more intuitive and preferable if there is one.
using System.Data.Metadata.Edm;
using System.Data.Objects;
using System.Data.Entity.Infrastructure;
...
using (dbcontext context = new TestContext())
{
ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext;
MetadataWorkspace workspace = objContext.MetadataWorkspace;
IEnumerable<EntityType> tables = workspace.GetItems<EntityType>(DataSpace.SSpace);
}
Thanks,
Will

Related

Using code-first approach,I don't have an edmx file. what's the alternative?

I'm fairly new to asp.net mvc, so please bear with me.
I want to implement a calendar functionality, and all the tutorials I've looked at use database-first approach and have the edmx file (Entity Data Model)
I'm using code first and what can I do regarding the code that references this edmx file? do I reference context instead?
example:
public JsonResult GetEvents()
{
//Here MyDatabaseEntities is our entity datacontext (see Step 4)
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
var v = dc.Events.OrderBy(a => a.StartAt).ToList();
return new JsonResult { Data = v, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
Sorry if this question is vague or not clear.
Thank you and I'd appreciate help!
In code first, you don't need an edmx file, because everything is in your own code. The basic building blocks are:
A class that inherits from DbContext. This will be equivalent to the MyDatabaseEntities class in your sample.
A set of entity classes. They basically just need to be plain classes with auto properties corresponding to your database columns. For built in conventions to work, you also need an ID, for instance an int property named Id
A set of properties on your DbContext class of type DbSet for every type T which is an entity you would like to query against. This is the Events property in your example.
In more advanced scenarios you customize the mappings beyond what the conventions can infer automatically. This can be done with attributes on your entity classes, or via a special set of APIs that can be called on your context at startup
Go to Sql server inside your database there is a folder Database Diagram, Right click New Database Diagram and explore it.

EF6 equivalent of EF Core's QueryTrackingBehavior.NoTracking

I am searching for a way to globally disable change tracking in my Context class. This will prevent developers from forgetting to put .AsNoTracking() on each repository query as we currently do. This will also prevent us from manually having to .Detach() entities on occasion. I have found a solution in EF Core which is to do something like the following:
public class MyContext : DbContext
{
public MyContext() {
ChangeTracker.QueryTrackingBehavior =
QueryTrackingBehavior.NoTracking;
}
public DbSet<MyEntity> MyEntities {get;set;}
}
However, the Context class in Entity Framework 6 does not appear to have a QueryTrackingBehavior property on it's ChangeTracker. Is there a way to accomplish this using Entity Framework 6?
Please note that I have already looked into using AutoDetectChangesEnabled = false and it does not work for the reasons outlined here.
All help is appreciated.
No, there is no similar functionality in EF6

Why does Entity Framework automatically use the ObjectContext instead of the DbContext when mapping database tables using ADO.NET Entity datamodel

I am following the database approach first; I have created the tables in my SQL Server 2008 database, then I map those tables to Entity Framework classes using an ADO.NET Entity Data Model. But when I opened the designer.cs file I found the following code in the class definition which was created automatically:
public partial class PortalEntities : ObjectContext
so I have the following three question that get my confused:
Why does my PortalEntities class derive from ObjectContext and not DbContext as I was expecting?
Is there a major difference between ObjectContext & DbContext, or they are mainly the same and offer that same capabilities
When I try to write the something similar to the following code:
Student student = db.Students.Find(id);
I found that I cannot use .Find() method as I used to do using DbContext, so does this mean that ObjectContext & DbContext have different methods that I can use?
BR
The DbContext is a wrapper around the ObjectContext which simplifies the interface for the things we do most.
If you have an DbContext you can still access the ObjectContexttrough ((IObjectContextAdapter)dbContext).ObjectContext;
If you want to use the DbContext instead of the ObjectContext when using database first, you can switch the template that's used for generating your code. You can do this by right-clicking in your EDMX and selecting 'Add Code Generation Item'. You can then select the DbContext template.
Here is an example of the whole process.
Since VS2012 the default code generation changed from ObjectContext to DbContext.

ADO.Net EF, Inheritance Table shows, but not the model

I have created a Entity named MediaItem which is Abstract and Game inherits form it. I create the database automatically and I get a table MediaItems and MediaItems_Game.
The issue is when I do the following in my ASP.Net Controller:
private Models.DBContainer dataModel = new DBContainer();
dataModel. ---> Intellisense shows me MediaItem but I can find no way to either navigate to or use MediaItems_Game, how can I solve this? i.e. How can I grab a list of 'Games' with some 'WHERE' constraints on another table (not pictured).
Any info is appreciated, thanks.
This is how inheritance in EF works. You have only single set of parent type. If you want to get just games you will use OfType method:
var games = dataModel.MediaItems.OfType<Game>().ToList();

Mocking DbEntityEntry.CurrentValues.SetValues() in EF4 CTP5 Code First

I am trying to use the DbEntityEntry.CurrentValues.SetValues() method to facilitate updating an existing entity with values from a non-entity DTO (see: http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx)
I'm having trouble removing the dependency on DbEntityEntry though (for mocking, testing). Here is an example of what I would like to do:
var entity = dbSet.Find(dto.Id);
var entry = context.Entry(entity);
entry.CurrentValues.SetValues(dto);
context.SaveChanges();
I've also considered:
EntityType entity = new EntityType() { Id = dto.Id };
context.Attach(entity);
var entry = context.Entry(entity);
entry.CurrentValues.SetValues(entity);
context.SaveChanges();
From what I've been able to find both seem reasonable when working with an actual DbContext, but when I abstract the context to an IMyContext I lose the capability to get a DbEntityEntry for an entity, thus losing the SetValues option.
Is there any way to work around this issue, or do I need to bite the bullet and manually set modified properties on the entity from the DTO (potentially a lot of boilerplate for entities with many properties)?
(I'm fairly new to EF and this is my first StackOverflow question, so please be gentle)
If you have never used it before, this would be a great use for AutoMapper (also available via NuGet). I am unaware of how to solve your IMyContext issue and would also resort to mapping the properties. But instead of doing so manually, I would allow AutoMapper to do the heavy lifting.

Resources