EF 6 - How to get DbSet by table name - entity-framework

I have a DbContext that looks like this:
public partial class MyDbConnectionConnection : DbContext
{
public MyDbConnectionConnection()
: base("name=MyDbConnectionConnection ")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Name> tbName{ get; set; }
public DbSet<Surname> tbSurname{ get; set; }
public DbSet<Address> tbAddress{ get; set; }
public DbSet<Currency> tbCurrency { get; set; }
}
}
and I need to search through this Context and find data set that matches the table name for example:
public dynamic getCorrectEntity()
{
MyDbConnectionConnection Context = new MyDbConnectionConnection();
var dbset = Context.Set(Type.GetType("tbName"));
return dbset;
}
where "tbName" is name of DbSet.
I cannot get anything!
In this line of code Type.GetType("tbName") it returns value null.
I just need to mentioned that I googled, try all examples I found here in the last couple of hours but nothing helps :(
Does anyone know how to get entity on this way?
P.S. I also try all this using Assembly.GetType(name). It didn't help...

Related

Entity framework keeps inserting duplicate objects when adding

I could really need some help in order to solve this issue. When I try to add an entity using Entity Framework, it keeps adding 1 more than needed.
Here you see my database after I have added 2 movies.
As you see, it adds the same movie "The rock" twice.
Been looking into the problem the past two days, but haven't found a solution that don't giving my exceptions.
Code:
public bool Execute(RequestedMovie movie)
{
using (var context = new MoviesContext())
{
context.RMovies.Attach(movie);
context.RMovies.Add(movie);
context.SaveChanges();
}
return true;
}
Model:
public class RequestedMovie
{
[Key]
public int RequestedMoviesID { get; set; }
public string MovieId { get; set; }
public string MovieTitle { get; set; }
public string MovieLink { get; set; }
public string MovieYear { get; set; }
public int MovieQuality { get; set; }
public string Requester { get; set; }
public bool Status { get; set; }
}
DataContext:
public class MoviesContext : DbContext, IMoviesContext
{
public MoviesContext() : base("MoviesContext")
{
}
// DbSet to bookings
public DbSet<Movie> Movies { get; set; }
public DbSet<RequestedMovie> RMovies { get; set; }
public void MarkAsAdded(Movie item)
{
Entry(item).State = EntityState.Added;
}
public void MarkAsDeleted(Movie item)
{
Entry(item).State = EntityState.Deleted;
}
public void MarkRequestedMovieAsAdded(RequestedMovie item)
{
Entry(item).State = EntityState.Added;
}
public void MarkRequestedMovieAsModified(RequestedMovie item)
{
Entry(item).State = EntityState.Modified;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
This should be pretty strait forward, because I only have one table which I'm going to add to. Have tried with the Attach approach that I found in another Stack post, but it still won't work :(.
Have also tried using the methods (MarkRequestedMovieAsAdded) I have in my context file, instead of RMovies.Add(objekt), but same result.
What could be wrong here?
Just use:
context.RMovies.Add(movie);
context.SaveChanges();
I managed to solve this issue. I haven't done any mistake in the Web Api. It turned out that my Angular2 observable calls made an error and called my web api twice because it was (cold) and not (warm).
Here is the post about it:
Angular2 http.post gets executed twice
All I should do was add .share() after mapping in my angular2 service.

check if a property is ignored by EntityFramework

Using EntityFramework 4.3 w/POCOs.
how can I check if a property on a model is ignored or not.
In my DBContext Class Hierarchy I am ignoring a property by
modelBuilder.Entity<EClass>().Ignore (f => f.IgnoredProperty());
In my BaseContext class, I need to check if that property is ignored or not.
private void ProcessGlobalConvention(DbModelBuilder modelBuilder, IGlobalConvention convention)
{
modelBuilder.Entity<typeof(this.GetType())>("Ignored Property");
}
How can I do that?
Thanks
Use the EF power tools http://www.infoq.com/news/2013/10/ef-power-tools-beta4 to view your model. Is the property there?
Create a database. Is the column there?
Look at the Database.LogSqlEvents http://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/ and parse the sql to see if the field name appears...
....unless you really want a code solution...?
IN WHICH CASE
New up your DbContext
Create one record and add it to the relevant DbSet
Get the DbEntityEntry
Look in CurrentValues.PropertyNames. Is your property there?
[TestMethod]
public void CreateDatabase()
{
Database.SetInitializer(new DropCreateDatabaseAlways<HomesContext>());
var db = new HomesContext();
Assert.IsFalse(db.Homes.Any());
var home = db.Homes.Create();
db.Homes.Add(home);
var entry = db.Entry(home);
Assert.IsTrue(entry.CurrentValues.PropertyNames.Contains("MaxResidents"));
Assert.IsTrue(entry.CurrentValues.PropertyNames.Contains("MaxStaff"));
Assert.IsFalse(entry.CurrentValues.PropertyNames.Contains("CurrentResidents"));
Assert.IsFalse(entry.CurrentValues.PropertyNames.Contains("CurrentStaff"));
}
public class HomesContext:DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Home>().Ignore(x => x.CurrentResidents);
base.OnModelCreating(modelBuilder);
}
public DbSet<Home> Homes { get; set; }
}
public class Home
{
public int HomeId { get; set; }
public string HomeName { get; set; }
public int MaxResidents { get; set; }
public int MaxStaff { get; set; }
public int CurrentResidents { get; set; }
[NotMapped]
public int CurrentStaff { get; set; }
}

Why is EF code first throwing model backing context exception? Using 4.0.3

Heres the exception:
The model backing the 'ScannerContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database (http://go.microsoft.com/fwlink/?LinkId=238269).
I get this everytime I run my application. I cant figure out what it means. I think it means something isn't mapped correctly, but I cant figure out what. I am using the code first model, and I have an existing database that I want totally custom mappings for. Right now, I have everything in my classes named the same as my database to eliminate possible cuases.
The Exception is thrown when I try to .Add() the entity to the context.
The Entity as it is in the Database
The Entity in my DataLayer
public class EAsset
{
public int i_GID { get; set; }
public EAssetType Type { get; set; }
public EOrgEnvironment Environment { get; set; }
public EUser Contact { get; set; }
public string s_Name { get; set; }
public string s_Role { get; set; }
public DateTime d_Added { get; set; }
public DateTime d_LastUpdated { get; set; }
public bool b_Retired { get; set; }
public EAsset()
{
Type = new EAssetType();
Environment = new EOrgEnvironment();
Contact = new EUser();
d_Added = DateTime.Now;
d_LastUpdated = DateTime.Now;
}
}
The Context Object (with attempted table mapping and key assignment)
public class ScannerContext : DbContext
{
public ScannerContext()
: base("LabDatabase") { }
public DbSet<EAsset> EAssets { get; set; }
public DbSet<EAssetType> EAssetTypes { get; set; }
public DbSet<EOrgEnvironment> EOrgEnvironments { get; set; }
public DbSet<EUser> EUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EAsset>().HasKey(k=>k.i_GID).ToTable("t_Assets");
modelBuilder.Entity<EAssetType>().HasKey(k => k.i_ID).ToTable("t_Asset_Types");
modelBuilder.Entity<EOrgEnvironment>().HasKey(k => k.i_ID).ToTable("t_Org_Environments");
modelBuilder.Entity<EUser>().HasKey(k => k.i_ID).ToTable("t_Users");
base.OnModelCreating(modelBuilder);
}
}
The Program
class Program
{
static void Main(string[] args)
{
EAsset Entity = new EAsset { s_Name = "jewri-pc" };
var sContext = new ScannerContext();
sContext.EAssets.Add(Entity);
sContext.SaveChanges();
}
}
For EF runtime version 4.0.3 / version 4.0
public class ScannerContext : DbContext
{
public ScannerContext()
: base("LabDatabase") { }
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<ScannerContext>(null); // <--- This is what i needed
...
base.OnModelCreating(modelBuilder);
}
}
With that code installed I am now chasing errors related to having all my relationships accounted for in the model. The FK Constraints are forcing me to add the missing relational items.
Found info here. They explain the importance a bit.
The model backing the <Database> context has changed since the database was created
Enable-Migrations -ContextTypeName EmployeeProject.Models.DepartmentContext
Means you have to write your project name.Models.Context name
It will work.

Entity framework - Invalid Object Name

I have a project where i use EF 4.1.
At Data Context:
public DbSet<Customer> Customer { get; set; }
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder) { }
Entity model class:
[Table("User",SchemaName="dbo")]
public class User{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Once I run the application I was getting following error.
Invalid object name dbo.User
Why? What is wrong?
What is in your OnModelCreating method?
Try to remove default plural table name:
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
If you happen to be using configuration mapping (EntityTypeConfiguration) classes to define your tables, you'll get this error if you forget to attach the Configuration class for the table to the Model Builder.
In my case, it really stumped me for a bit, because I already had another table (SomeThing) working perfectly within this Context class. After simply adding a new table (OtherThing) where everything seemed to be setup identical to the first, I got the error: Invalid object name 'dbo.OtherThings.
The answer was in my Context class:
public DbSet<SomeThing> SomeThings { get; set; }
public DbSet<OtherThing> OtherThings { get; set; }
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new SomeThingMap());
// OOPS -- Forgot to add this!!
modelBuilder.Configurations.Add(new OtherThingMap());
}
For reference, here's my SomeThingMap class:
public class SomeThingMap : EntityTypeConfiguration<SomeThing>
{
public SomeThingMap()
{
...
this.ToTable("SomeThing");
...
}
}
And my new OtherThingMap class:
public class OtherThingMap : EntityTypeConfiguration<OtherThing>
{
public OtherThingMap()
{
...
this.ToTable("OtherThing");
...
}
}
It's a long shot, but I hope this helps point someone else in the right direction, at least.

How to map an Entity framework model to a table name dynamically

Using a code-first approach I'd like to map a single model to multiple table names dynamically. Currently I can do something like modelBuilder.Entity(Of Person)().MapSingleType().ToTable("Managers") but as the OnModelCreating method is only called once I can't map it to other table names on the fly.
In our current LinqToSql version we're overriding the MetaModel.GetTable() and returning a new TableAttribute with our dynamic name. I haven't found an attribute like that in EF (even if there were I wouldn't know how to override that yet). So my question is: Is it possible to do this (yet)?
Update
I've found that I can prevent the OnModelCreating method from caching the mappings by calling
modelBuilder.CacheForContextType = false;
As a result I can assign table definitions on instantiation of the object. This isn't quite how I wanted to do it but it works.
Update
Oh boy, was the above a big mistake...Caching exists for a reason! :) So I'm back to square one with POCO object mapping. I'll post an update if I figure out a solution.
Final
Incase anybody cares how I've currently solved this issue, here you go:
First I created a separate library with the POCO tables and an Interface
public interface IDataContext {
System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
int SaveChanges();
}
public class TableGeneric {
[Key]
public int Column1 { get; set; }
public string Column2 { get; set; }
public DateTime Column3 { get; set; }
public string Column4 { get; set; }
public string Column5 { get; set; }
}
Then, using the CSharpCodeProvider I created a class that takes the following template and turns it into a type definition:
class DataContext : System.Data.Entity.DbContext, IDataContext {
public System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder
.Entity<ContextTesting.Interfaces.EF.TableGeneric()
.MapSingleType()
.ToTable("$TableName$");
}
}
With the generated type I'm able to create an instance so here we go
Type typeAccountants = BuildContext.CreateGenericTable("Accountants");
IDataContext context = (IDataContext)Activator.CreateInstance(typeAccountants);
Then the rest is just as if you had a normal DataContext. Hope this helps someone else.
Incase anybody cares how I've currently solved this issue, here you go:
First I created a separate library with the POCO tables and an Interface
public interface IDataContext {
System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
int SaveChanges();
}
public class TableGeneric {
[Key]
public int Column1 { get; set; }
public string Column2 { get; set; }
public DateTime Column3 { get; set; }
public string Column4 { get; set; }
public string Column5 { get; set; }
}
Then, using the CSharpCodeProvider I created a class that takes the following template and turns it into a type definition:
class DataContext : System.Data.Entity.DbContext, IDataContext {
public System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder
.Entity<ContextTesting.Interfaces.EF.TableGeneric()
.MapSingleType()
.ToTable("$TableName$");
}
}
With the generated type I'm able to create an instance so here we go
Type typeAccountants = BuildContext.CreateGenericTable("Accountants");
IDataContext context = (IDataContext)Activator.CreateInstance(typeAccountants);
Then the rest is just as if you had a normal DataContext. Hope this helps someone else.