Schema invalid and types cannot be loaded because the assembly contains EdmSchemaAttribute - entity-framework

Getting the following error:
Schema specified is not valid. Errors:
The types in the assembly 'x, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null' cannot be loaded because the assembly contains
the EdmSchemaAttribute, and the closure of types is being loaded by
name. Loading by both name and attribute is not allowed.
What does this error mean exactly?
I'm trying to shoe-horn into my application an EF model from an existing database.
Before this application was based on CodeFirst and using the repository pattern but for the life of me I can't get this working.
Before I had:
public class BaseModelContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
}
But in a EF model-first scenario (one where tables already exist in the db), I had to remove these as it didn't seem to like having a repository pattern on DbSet properties.
So I stripped these out, and the repository can then use repository on the classes already defined on the .designer.cs context class (the EF model). This has the EdmSchemaAttribute set inside the generated code.
So how do I get my repository pattern to work in the model-first scenario? What does the above error mean exactly?
EDIT
Added new code:
public class BaseModelContext : DbContext
{
// public DbSet<Location> Locations { get; set; }
public BaseModelContext(string nameOrConnection)
: base(nameOrConnection)
{
}
public BaseModelContext()
{
}
}
public class VisitoriDataContext : BaseModelContext
{
public VisitoriDataContext()
: base("visitoriDataConnection")
{
}
}
public interface IVisitoriDataContextProvider
{
VisitoriDataContext DataContext { get; }
}
public class VisitoriDataContextProvider : IVisitoriDataContextProvider
{
public VisitoriDataContext DataContext { get; private set; }
public VisitoriDataContextProvider()
{
DataContext = new VisitoriDataContext();
}
}
public class VisitoriRepository<T> : IRepository<T> where T : class
{
protected readonly IVisitoriDataContextProvider _ctx;
public VisitoriRepository(IVisitoriDataContextProvider ctx)
{
_ctx = ctx;
}
public T Get(int id)
{
return _ctx.DataContext.Set<T>().Find(id);
}
}
public interface ILocationRepo : IRepository<Location>
{
IEnumerable<Location> GetSuggestedLocationsByPrefix(string searchPrefix);
}
public class LocationRepo : VisitoriRepository<Location>, ILocationRepo
{
public LocationRepo(IVisitoriDataContextProvider ctx)
: base(ctx)
{
}
public IEnumerable<Location> GetSuggestedLocationsByPrefix(string searchPrefix)
{
return Where(l => l.name.Contains(searchPrefix)).ToList();
}
}

The error means that you cannot combine code first mapping (data annotations and fluent API) and EDMX mapping (with EntityObjects!) for entity with the same name. These two approaches are disjunctive.
The rest of your question is not clear.
Btw. building mapping from existing database is called database first not model first.

Decorate the assembly containing the GILayerModel type with [assembly: EdmSchema] attribute.

In my case, I had a class that derived from an entity (code-first class) in another assembly, and I was adding an instance of this class to the DBContext:
in DBEntities project:
public class GISLayer
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int GISLayerId { get; set; }
[StringLength(200)]
public string LayerName { get; set; }
public List<GISNode> Nodes { get; set; }
}
in the second assembly:
public class GISLayerModel : DBEntities.GISLayer
{
public new List<GISNodeModel> NodesModel { get; set; }
}
and the cause of error:
[WebMethod]
public void SaveGISLayers(GISLayerModel[] layers)
{
using (DBEntities.DBEntities db = new DBEntities.DBEntities())
{
foreach (var l in layers)
{
if (l.GISLayerId > 0)
{
db.GISLayers.Attach(l); //attaching a derived class
db.Entry(l).State = System.Data.EntityState.Modified;
}
else
db.GISLayers.Add(l); //adding a derived class
SaveGISNodes(l.NodesModel.ToArray(), db);
}
db.SaveChanges();
}
}
So, I used AutoMapper to copy properties of derived class to a new instance of base class:
DBEntities.GISLayer gl = AutoMapper.Mapper.Map<DBEntities.GISLayer>(l);
if (gl.GISLayerId > 0)
{
db.GISLayers.Attach(gl);
db.Entry(gl).State = System.Data.EntityState.Modified;
}
else
db.GISLayers.Add(gl);
That solved the problem.

Related

issue with new create dbcontext class object in asp.net core 2.1

I m new in .net core 2.1
I m working with .net core 2.1 with code first approach
issue is when I create a new object dbcontext class then give error see below line
dbcontextstudent db=new dbcontextstudent(); //here give an red line
appsettings.json
},
"ConnectionStrings": {
"sqlserverconn": "Server=DEVISSHAHID; Database=studdbs; User id=xxxx;Password=xxxxx;"
},
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//connection string
services.AddDbContext<DbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("sqlserverconn")));
student.cs
namespace WebApplication1.Models
{
public class student
{
[Key]
public int studid { get; set; }
public string studname { get; set; }
public string studsalary { get; set; }
public int studage { get; set; }
}
}
dbcontextstudent.cs
namespace WebApplication1.Models
{
public class dbcontextstudent : DbContext
{
public dbcontextstudent(DbContextOptions<dbcontextstudent> options) : base(options)
{
}
public DbSet<student> stud { get; set; }
}
}
HomeController.cs
I m not understood the above intellisense
I write the code as per intellisense but still give an error I know error is clear but not solved
which place doing I m wrong?
You will have to pass your DbContext type to the AddDbContext method in ConfigureServices method like this:
services.AddDbContext<dbcontextstudent>(options => options.UseSqlServer(Configuration.GetConnectionString("sqlserverconn")));
After that, you have registered the dbcontextstudent class in dependency injection.
You shouldn't create the instance of dbcontextstudent on your own like you did:
dbcontextstudent db=new dbcontextstudent();
Instead you can inject it though the constructor of your controller like this:
public HomeController : Controller
{
private readonly dbcontextstudent _db;
public HomeController(dbcontextstudent db)
{
_db = db;
}
... and then you can use the _db variable in your post action
}

EF5 Code first TPH Mapping error using DBSet.Find()

When using Entity Framework 5 Code First, with Table Per Hierarchy.
This combined with a Repository and Unit of Work (tried several implementations).
I'm having the following error:
(34,10) : error 3032: Problem in mapping fragments starting at lines 19, 34:EntityTypes T, T are being mapped to the same rows in table T. Mapping conditions can be used to distinguish the rows that these types are mapped to.
I have resolved this issue using the following guide:
Entity Framework 4.3 - TPH mapping and migration error
This works when using a general look-up of all records, then no errors.
When using the DBSet<T>.Find(id), I receive the above error message.
When using DBSet<T>.Where(t => t.id == id) all works fine.
Please does anyone have the solution for this problem?
public class TDataContext : DbContext
{
// Models
public abstract class BaseTrackable
{
public DateTime DateModified { get; set; }
}
public abstract class ParentClass : BaseTrackable
{
public int ParentId { get; set; }
public string ParentString { get; set; }
}
public class Foo : ParentClass
{
public string FooString { get; set; }
}
public class Bar : ParentClass
{
public string BarString { get; set; }
}
// Configuration
public class ParentConfiguration : EntityTypeConfiguration<ParentClass>
{
public ParentConfiguration()
{
ToTable("Parent");
}
}
public class FooConfiguration : EntityTypeConfiguration<Foo>
{
public FooConfiguration()
{
Map(m => m.Requires("FooIndicator").HasValue(true));
}
}
public class BarConfiguration : EntityTypeConfiguration<Bar>
{
public BarConfiguration()
{
Map(m => m.Requires("BarIndicator").HasValue(true));
}
}
public DbSet<ParentClass> Parent { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations
.Add(new ParentConfiguration())
.Add(new FooConfiguration())
.Add(new BarConfiguration());
}
}
public class Controller
{
TDataContext _context = new TDataContext();
// Repository function
public T GetById<T>(object id) where T : class
{
var dbset = _context.Set<T>();
return dbset.Find(id);
}
public IQueryable<TDataContext.Foo> GetFiltered(Expression<Func<TDataContext.Foo, bool>> filter)
{
var dbset = _context.Set<TDataContext.Foo>();
return dbset.Where(filter);
}
// Final call
// Which fails..
public TDataContext.Foo Get(int id)
{
return this.GetById<TDataContext.Foo>(id);
}
// This works...
public TDataContext.Foo GetWhere(int id)
{
return this.GetFiltered(f => f.ParentId == id).FirstOrDefault();
}
}
Found something that solves my problem partially...
When adding another indicator to the tables, there is no more error, example:
public class FooConfiguration : EntityTypeConfiguration<Foo>
{
public FooConfiguration()
{
Map(m => {
m.Requires("FooIndicator").HasValue(true);
m.Requires("BarIndicator").HasValue<short>(1);
});
}
}
public class BarConfiguration : EntityTypeConfiguration<Bar>
{
public BarConfiguration()
{
Map(m => {
m.Requires("BarIndicator").HasValue(true);
m.Requires("FooIndicator").HasValue<short>(0);
});
}
}
Wouldn't be better
public class FooConfiguration : EntityTypeConfiguration<Foo>
{
public FooConfiguration()
{
Map(m => m.Requires("Type").HasValue("Foo"));
}
}
public class BarConfiguration : EntityTypeConfiguration<Bar>
{
public BarConfiguration()
{
Map(m => m.Requires("Type").HasValue("Bar");
}
}
In this way FooConfiguration doesn't need to know anything about BarConfiguration and visa versa. I had this issue when migrating from EF 4.3 to 5.0 and I think what has changed was the discriminator database columns are not nullable in EF 5.0. I think it makes much more sense for them to be not nullable and in general it might be better to have only one discrimanotor column for each derived type as opposed to one column per type (as it was in EF 4.3)
-Stan

Use a base class as the return type in ApiController

Using the ASP.NET WebApi 4 RC, is it possible to have an ApiController's return type be a base class and actually return instances of derived classes? Trying to do this now results in an internal server error (500) when returning xml. Returning json using this method works correctly.
public class Base
{
public int ID { get; set; }
}
public class Derived : Base
{
public string Message { get; set; }
}
public class ValuesController : ApiController
{
public IEnumerable<Base> Get()
{
return new Derived[] {
new Derived(){ Message="test"},
new Derived(){ Message="another"}
};
}
}
It would seem that the XML serialization is what's throwing the error but all I can see is the generic 500 error.
Yes, you need to use the knowntype serialization hint:
[System.Runtime.Serialization.KnownType(typeof(Derived))]
public class Base
{
public int ID { get; set; }
}
You might want to do it programmatically
private static Type[] GetKnownType()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var knownTypes = new List<Type>();
foreach (var assembly in assemblies)
{
knownTypes.AddRange(assembly.GetTypes().Where(x => x.BaseType == typeof (BaseResponse)).ToArray());
}
return knownTypes.ToArray();
}
Do remember your child class MUST have a default constructor else you will get runtime serialization error.

Entity Framework 4.1 insert error

i have written a generic repository for my base windows which have a problem with.
lets be more specific, there is a little poco class called Unit as following:
public class Unit : BaseEntity
{
public string Name { get; set; }
private ICollection<Good> _goods;
public virtual ICollection<Good> Goods
{
get
{
if(_goods==null)
{
return new List<Good>();
}
return _goods;
}
set { _goods = value; }
}
}
which is inherited from a base entity class as :
public class BaseEntity
{
public int Id { get; set; }
public override string ToString()
{
return Id.ToString();
}
}
and this is my Add section of generic repository class:
public void Add(TEntity entity)
{
if (entity == null) return;
if (Context.Entry(entity).State == EntityState.Detached)
{
Context.Set<TEntity>().Attach(entity);
}
Context.Set<TEntity>().Add(entity);
Context.SaveChanges();
}
before add a new record, max id is fetched from db and placed in IdTextBox and them add method of base form is called which calls aforementioned Add method of base repository. here is the problem, i get this error, "The property 'Id' is part of the object's key information and cannot be modified."
there is also a mapper class that maps every property to its corresponding control which does its job fine.
What is my problem?
Thanks in advance.
i figured out that this problem is occured because of auto detect changes enability which was true.

MVC3 + Ninject + Entity framework 4

i have this Dependency resolver
public class NinjectDependencyResolvercs : IDependencyResolver
{
private readonly IResolutionRoot resolutionRoot;
public NinjectDependencyResolvercs(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
return resolutionRoot.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return resolutionRoot.GetAll(serviceType);
}
}
in global.asax.cs
// Ninject DI container ----------------------------------------------------------- |
public void SetupDependencyInjection()
{
// Create Ninject DI kernel
IKernel kernel = new StandardKernel();
#region Register services with Ninject DI Container
// DbContext to SqlDataContext
kernel.Bind<DbContext>()
.To<SqlDataContext>();
// IRepository to SqlRepository
kernel.Bind<IRepository>()
.To<SqlRepository>();
// IUsersServices to UsersServices
kernel.Bind<IUsersServices>()
.To<UsersServices>();
// IMessagesServices to MessagesServices
kernel.Bind<IMessagesServices>()
.To<MessagesServices>();
// IJobAdvertsServices to JobAdvertsServices
kernel.Bind<IJobAdvertsServices>()
.To<JobAdvertsServices>();
#endregion
// Tell ASP.NET MVC 3 to use Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolvercs(kernel));
}
// --------------------------------------------------------------------------------- |
and class
public class SqlDataContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Profile> Profiles { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<JobAdvert> JobAdverts { get; set; }
public DbSet<Message> Messages { get; set; }
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(x => x.Roles).WithMany(x => x.Users).Map(x =>
{
x.MapLeftKey(y => y.UserId, "UserId");
x.MapRightKey(y => y.RoleId, "RoleId");
x.ToTable("UsersInRoles");
});
base.OnModelCreating(modelBuilder);
}
}
all dependecies work fine but for DbContext to SqlDataContext is problem. If use this:
public class SqlRepository
{
private DbContext dataContext;
public SqlRepository(DbContext dataContext) {
this.dataContext = dataContext;
}
public DbSet<User> Users {
get {
return dataContext.Users;
}
}
}
then
dataContext.Users
and all others properties alert this error:
'System.Data.Entity.DbContext' does not contain a definition for 'JobAdverts' and no extension method 'JobAdverts' accepting a first argument of type 'System.Data.Entity.DbContext' could be found (are you missing a using directive or an assembly reference?)
Have anyone any idea why DI doent work for Class DbContext ?
If I understand correctly, You're injecting DbContext which doesn't have those methods/properties, as they're declared in the derived type SqlDataContext.
You need to inject the SqlDataContext. If you want to use an interface, you'll need to extract an interface from SqlDataContext.
EDIT:
Ninject binds at runtime while the errors you're getting (I presume) are at compile time. You could get around this by using the dynamic key word, but that's just working AROUND the problem.
public class SqlRepository
{
private dynamic dataContext;
public SqlRepository(DbContext dataContext) {
this.dataContext = dataContext;
}
...
}
What you need to do is change the signature to use your SqlDataContext:
public class SqlRepository
{
private SqlDataContextdata Context;
public SqlRepository(SqlDataContextdata Context) {
this.dataContext = dataContext;
}
...
}
because DbContext does not contain those methods, only your SqlContext does. and your sqlcontext is bound to DbContext at runtime.