Schema not supported error in asp.net mvc web api - entity-framework

I am working on asp.net mvc 4 web api. I am using code first with existing database model. I have a single table in my database so i have the entity class like,
public class Tab1
{
[Key]
public int Field1{get; set;}
public string Field2{get; set;}
}
I have DBContext file like,
public class MyDBContext:DbContext
{
public DbSet<Tab1> Table{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Bar>().ToTable("bars");
}
}
and my Get Action is like
public List<Bar> GetTables()
{
MyDBContext context=new MyDBContext();
return context.Table.ToList();
}
But I am getting an error Schema specified is not valid error 0064: Facet 'MaxLength' must not be specified for type 'mediumtext'.. so please guide if i did any mistake in the process.
Here i have one more class like
public class Tab2:Tab1
{
public string Filed3{get; set;}
}
I dont want to create table in database with tab2 since i used tab2 class for returning custom records. I got the above error due to Tab2 inheriting from tab1 when i remove class tab2 it works as usual. so please guide me.

If you problem is only caused when introducing the "Tab2" class in the model and you don't really want "Tab2" to be stored in the database why don't you just annotate the "Tab2" class with the the [NotMapped] attribute or use the fluent configuration ModelBuilder.Ignore.

Related

Adding Entity Framework core code first sublass with existing property name

What is best/a good practise in the following situation when using TPH inheritance in Entity Framework?:
I have
abstract class Base
{
...
}
class Sub1
{
public int Amount {get;set;}
}
and a DbContext with:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Sub1>();
}
public DbSet<Base> Bases { get; set; }
Now I add
class Sub2
{
public int Amount { get; set; }
}
and
modelBuilder.Entity<Sub2>();
Before adding Sub2, Sub1.Amount was mapped to a "Amount" column in the Bases table. After adding Sub2, Sub1.Amount is mapped to a "Sub1_Amount" column and Sub2.Amount is mapped to the "Amount" column. The table has data in it, so the new "Sub1_Amount" column are all nulls. When I try to run the system, I get
An exception occurred while reading a database value for property 'Sub1.Amount'. The expected type was 'System.Int32' but the actual value was null.
I understand why this is happening...but I thought Migrations would handle this.
Does anyone one know how to handle this? Thanks!

EF share class from two dbcontext

I want to try to share a class (es. user) from two dbcontext.
The idea is 1st dbcontext has all method to work with user (add/remove/update/etc) the 2nd dbcontext only need to access (read the user data).
To do that I have created a class abstract Users and I add this class to the db context, so the problem is when create the migration for the 1st dbcontext and the 2nd.
In my 1st I want to track the changes on my POCO user class in the second I don't want to track/create the table.
I try to use Ingore on OnModelCreating but in this way the code first not create the migration but dbcontext don't have the correct model creating and I'm not able to do operation to table db (i use this approch suggested on EF Data Pints
--Update--
[Table("User")]
public abstract class BaseUser {
[Key]
public virtual int Id {get;set;}
public virtual string Name {get;set;}
}
//DB context 1
public class OUser : BaseUser{
}
public class oneDbContext : DbContext
{
public virtual IDbSet<OUser> OneUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
....
}
//DB context 2
public class MUser : BaseUser{
}
public class twoDbContext : DbContext
{
public virtual IDbSet<MUser> TwoUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Ignore<MUser>();
}
So now if I call the code first with Add-Migration whith modelBuider.Ingore the table User not appear in the script but when I try to access to table via db context I catch the error
The entity type Muser is not part of the model for the current context.
But if I uncomment the ingore the access to table work fine but model try to add the table User.

EntityFramework how to not map a class but do map it's inherited properties

We use EntityFramework 6.1 with CodeFirst in our web mvc application (StdWebApp). Now we want to make a new custom version of this application (CustomWebApp) .
The CustomWebApp will use most of the code of the standard one, in it's domain model it will extend the Person class.
In CustomDomain we make implement a new DbContext that must connect with the database of the custom app (CustomSqlDb).
In (C#) code there is no problem that there is a Person in Domain and in CustomDomain. However we have not been able to devise a mapping for Person in the Custom DbContext that will:
Create a single "Person" table.
Contains fields form "CustomDomain.Person" AND those from "Domain.Person".
We tried some variants like this:
modelBuilder.Entity<Person>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Person");
}
);
using this document as our inspiration msdn mapping types
But EF complains about the simple name beeing equal.
Obviously we could rename the "Person" in "CustomDomain" to "PersonCustom" but that could lead to a lot of silly names if we have to do this again in the future like "PersonCustomExtraSpecial" etc.
Thoughts anyone?
UPDATE
we tried the solution suggested by mr100, here is the complete code:
namespace Domain
{
public class Person
{
public int Id { get; set; }
public string Stuff { get; set; }
}
}
namespace CustomDomain
{
public class Person : Domain.Person
{
public string ExtraStuff { get; set; }
}
}
namespace CustomDomain
{
public class DbModel : DbContext
{
DbSet<CustomDomain.Person> Persons { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<CustomDomain.Person>().Map(m => m.ToTable("Person"));
}
}
}
This still result in the error
The type 'CustomDomain.Person' and the type 'Domain.Person' both have the same simple name of 'Person' and so cannot be used in the same model. All types in a given model must have unique simple names. Use 'NotMappedAttribute' or call Ignore in the Code First fluent API to explicitly exclude a property or type from the model.
So we added the following code:
namespace CustomDomain
{
public class DbModel : DbContext
{
DbSet<CustomDomain.Person> Persons { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<Domain.Person>();
modelBuilder.Entity<CustomDomain.Person>().Map(m => m.ToTable("Person"));
}
}
}
Still same result.
To achieve this your DbContext class in CustomWebApps should have property People defined like this:
public DbSet<CustomDomain.Person> People {get; set;}
and no property:
public DbSet<Domain.Person> People {get; set;}
even if it comes from StdWebApp DbContext class from which CustomWebApp DbContext class may derive (if that is the case for you). Additionally you may set properly table name:
modelBuilder.Entity<Person>().ToTable("Person");

entity framework code first and view mapping

I have a application using code first; in search section I have to gather information from 3 tables and their related tables so I made a view; and since there is no syntax for code first to create view (I think so; please let me know if I'm wrong) I used pure SQL script;
on model creating to prevent EF to create a table with same name as table (VIEW_SEARCH) I did :
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<View_Search>();
}
any ways application works fine until you try to get data from the view then BANG...
The model backing the 'SearchContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269)
This error simply says that what you have in your model file is inconsistent with what you have in your database.
To make it consistent go to Package Manager Console and type Enable-Migrations, then Add-Migration yourMigrationName and Update-Database. The error should disappear.
If you want to combine data from 3 tables you can simply create a ViewModel.
Let's say you have 3 models: Book, Author, BookStore and you want to have all information in one view. You create ViewModel
public class MyViewModel
{
public Book myBook {get; set;}
public Author myAuthor {get; set;}
public BookStore myBookStore {get; set;}
}
Then you add at the top of your all-in-one-view
#model myNamespace.MyViewModel
and access items like
Model.Book.title
Model.Author.name
Model.BookStore.isClosed
I'm actually working with Entity Framework "Code First" and views, the way I do it is like this:
1) Create a class
[Table("view_name_on_database")]
public class ViewClassName {
// View columns mapping
public int Id {get; set;}
public string Name {get; set;}
// And a few more...
}
2) Add the class to the context
public class ContextName : DbContext {
// Tables
public DbSet<SomeTableClassHere> ATable { get; set; }
// And other tables...
// Views
public DbSet<ViewClassName> ViewContextName { get; set; }
// This lines help me during "update-database" command
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
// Remove comments before "update-database" command and
// comment this line again after "update-database", otherwise
// you will not be able to query the view from the context.
// Ignore the creation of a table named "view_name_on_database"
modelBuilder.Ignore<ViewClassName>();
}
}

Entity framework code-first ignores table mapping

We have a ef project using an existing legacy database, but adding new tables to it using ef-migrations. For these entities, we create tables using a new schema, to separate them from the legacy tables. We use the convention with plural form of the class name on the db tables.
However, when we add a new class to be mapped to a legacy table (without a plural table name), ef seems to ignore the mapping.
The entity class:
public class Aktor:IVersionedEntityWithId
{
public int Id { get; set; }
public string Navn { get; set; }
public byte[] Version { get; set; }
}
The mapping code:
protected virtual void MapAktor(EntityTypeConfiguration<Tilsyn.Domain.Aktor> config){
config.ToTable("dbo.Aktor");
config.Property(v=>v.Version).IsConcurrencyToken().IsRowVersion();
config.HasKey(e=>e.Id);
}
The exception:
System.Data.EntityCommandExecutionException: An error occurred while
executing the command definition. See the inner exception for details.
---> System.Data.SqlClient.SqlException: Invalid object name 'dbo.Aktors'.
It seems like the sql generated still ad an s to the class name to get the table name. What is missing in this picture? Am I using the ToTable method wrong?
Update: When changing the class name to something other than the table name, it seems to work. When changing the name back again, the problem has vansihed. Is there a EF cache or hidden mapping file somwehere?
Try overriding OnModelCreating() method in your DBContext subclass to create your mappings.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Tilsyn.Domain.Aktor>().ToTable("dbo.Aktor");
}