EF Codefirst fails to work with partial tables of northwind database - entity-framework

I could not work with employee table of Northwind database alone.
below code throws error as
"Unable to determine composite primary key ordering for type
'Northwind.Order_Detail'. Use the ColumnAttribute or the HasKey method
to specify an order for composite primary keys."
but it works fine, if I consider Order_details and other tables as well. and HasKey for OrderDetails table.
My Question is, is it not possible to work with few tables (Employee table alone in this case) using EF.
public partial class NorthwindEntities : DbContext
{
public NorthwindEntities()
: base("Northwind")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
SetupModels(modelBuilder);
}
public DbSet<Employee> Employees { get; set; }
}
Anand

Master table has navigation property to Order , Order details tables. that causes this error. after removing navigation properties in Employee table, it works fine.

Related

EF6 code first and VIEW

I would like to add a VIEW to the database, and query the data from this VIEW using L2E. I use migrations for maintaining database schema.
I added one class that should MAP to a VIEW columns. As an example, this class has only two properties
[Table("View_Data")]
public class ViewData
{
[Key]
public int Id { get; set; }
public int PropertyA { get; set; }
}
public class ViewDataMap : EntityTypeConfiguration<ViewData>
{
public ViewDataMap ()
{
this.ToTable("View_Data");
this.HasKey(t => t.Id);
}
}
I added ViewDataMap to OnModelCreating, as with any other Table mappings. I added DbSet ViewDatas.
When I executed
add-migration preview
it created new migration with CreateTable command. Since I do not want to create a table, but only a view, I replaced in UP() CreateTable with Sql("CREATE VIEW...")
Still, EF complains about pending changes in database, and still wants to create new migration with CreateTable()...
How can prevent EF to create new table, but use VIEW instead?
As Steve suggested in the comment, I forgot to do update-database, then all works as expected.

Unable to query new table from asp.net core web application using EF 1.0

I have developed a new asp.net Core web application using Visual Studio 2015. I am at the point where I am adding user customization options by adding additional tables to my local database. However I have been unable to add whatever EF needs to query a new table correctly. I get the following error when attempting to query the table..
Applying existing migrations for ApplicationDbContext may resolve this issue
There are migrations for ApplicationDbContext that have not been applied to the database
•00000000000000_CreateIdentitySchema
Apply Migrations
In Visual Studio, you can use the Package Manager Console to apply pending migrations to the database:
PM> Update-Database
Alternatively, you can apply pending migrations from a command prompt at your project directory:
dotnet ef database update
My table is a simple table with a few varchar or nvarchar columns. The model looks something like...
namespace MyNamespace.ColorSchemes
{
public class ColorSchemesViewModel
{
[Required]
public string Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string bc { get; set; }
}
Table looks something like this in SQL Server...
CREATE TABLE [dbo].[ColorSchemes](
[Id] [nvarchar](50) NOT NULL,
[Name] [varchar](32) NOT NULL,
[bc] [nchar](7) NOT NULL
)
I have added the table to the application context like such...
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<ColorSchemesViewModel> Colors { get; set; }
I have also used as separate class similarly like..
public DbSet<ColorSchemes> Colors { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
I have added the context to a controller like this...
private ApplicationDbContext _context;
public MyController(IMemoryCache memoryCache, ILoggerFactory loggerFactory, ApplicationDbContext context)
{
_memoryCache = memoryCache;
_logger = loggerFactory.CreateLogger<ChordMVCController>();
_context = context;
}
I have tried to query the table in my controller like this...
var colorSchemes = (from c in _context.Colors
select c).ToList();
I have attempted to use the Package Manager to per instructions from the error...
PM> Update-Database
I always get this error...
System.Data.SqlClient.SqlException: There is already an object named 'AspNetRoles' in the database.
This doesn't make sense since this table is already in the database and the EF definition. How do I get my table added properly to the EF migrations so I can query it?
I was able to solve this myself...
I created a different context rather than trying to embed the dbset in the default ApplicationDbContext and also removed the onModelCreating method.
public class ColorSchemeDbContext : DbContext
{
public ColorSchemeDbContext(DbContextOptions<ColorSchemeDbContext> options) : base(options)
{
}
public DbSet<ColorScheme> ColorSchemes { get; set; }
}
Replaced the ApplicationDBContext with the new context in my controller class...
private readonly ColorSchemeDbContext _context;
public MyController(IMemoryCache memoryCache, ILoggerFactory loggerFactory, ColorSchemeDbContext context)
{
_memoryCache = memoryCache;
_logger = loggerFactory.CreateLogger<ChordMVCController>();
_context = context;
}
After that the query worked. I spent a lot of time attempting to use the EF migrations to create the tables from a class syntax. Nothing seemed to work. I was creating a new .NET CORE web application in VS 2015 with the template and using user authentication which creates the AspNetRoles tables in SqlLite once you do an update-database. It is very confusing how to add additional tables using a code first approach after that. A lot more documentation is needed regarding EF migrations with respect to managing projects over time. I see the benefits of having all of your database updates maintained from your VS project but it is not easy to understand.

Map names for generated relationship tables in EF code first

I'm giving Code first a try and I have the requirement of a prefix of (all) my tables in db.
In my DbContext I have these entities:
public DbSet<Person> People { get; set; }
public DbSet<Department> Departments { get; set; }
I can successfully map table names for my entities by overriding:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().ToTable("w_people");
modelBuilder.Entity<Department>().ToTable("w_departments");
}
However for tables that created that don't directly map to a table I can't figure out to prefix.
In my example people can belong to many departments so a "non-entity" table is created by EF. (I'm a EF noob so these tables probably have a fancy name) So in my db I get three tables:
w_people
w_departments
PersonsDepartments
The PersonsDepartments table is what I'm after. How can I prefix these generated tables or change name/mapping after generation?
TIA
I have solved this:
modelBuilder.Entity<Person>().HasMany(p => p.Departments)
.WithMany(d => d.People)
.Map(mc => mc.ToTable("w_peopledepartments"));

Why do I get a "relationship multiplicity violation" accessing a relation property?

I have the following classes in which I am trying to map the entity object to the view model:
public class ConsumerIndexItem: MappedViewModel<Consumer>
{
public string UserName { get; set; }
public string RoleDescription { get; set; }
public override void MapFromEntity(Consumer entity)
{
base.MapFromEntity(entity);
UserName = entity.User.UserName;
}
}
public class Consumer: AuditableEntity
{
public virtual User User { get; set; }
public virtual Role Role { get; set; }
}
public class IndexModel<TIndexItem, TEntity> : ViewModel where TEntity : new()
{
public IndexModel()
{
Items = new List<TIndexItem>();
}
public List<TIndexItem> Items { get; set; }
public virtual void MapFromEntityList(IEnumerable<TEntity> entityList)
{
Items = Mapper.Map<IEnumerable<TEntity>, List<TIndexItem>>(entityList);
}
}
public class ConsumerIndexModel: IndexModel<ConsumerIndexItem, Consumer>
However, if I drive the mapping with the following code:
var model = new ConsumerIndexModel();
var list = _repository.List().Where(c => c.Parent == null).ToList();
model.MapFromEntityList(list);
return View(model);
on the line UserName = entity.User.UserName; in ConsumerIndexItem I get the following exception:
A relationship multiplicity constraint violation occurred: An EntityReference can have no more than one related object, but the query returned more than one related object. This is a non-recoverable error.
If I execute ?entity.User.UserName in the Immediate Window I get the expected user name value. What could be wrong here?
Let me explain why I had this exception and you may be able to correlate it with your own situation. I had EF Code First model mapped to the existing database. There was one-to-many relationship between two of the entities. The child table had composite primary consisting of the Id and Date. However, I missed the second segment of the primary key in my fluent map:
this.HasKey(t => t.Id);
The strange part of that was that the model worked but was throwing an exception in certain cases and it was very hard to understand why. Apparently when EF was loading the parent of child entity there were more than one parent since the key had not only Id but Date as well. The resolution was to include the second part of the key:
this.HasKey(t => new { t.Id, t.Date });
The tool that helped me to pinpoint the problem was EF Power Tools, currently it is in Beta 3. The tool gives a context menu for the EF context class where one the item is View Entity Model DDL SQL. Although I could have found this just by checking the code, the tool is nice in showing how close the EF model matches the actual database.
I believe that you're getting this exception because for a some reasons the multiplicity of relationship is violated. In my case it was incorrect mapping, in your it may be something else, I can't tell by looking at your code.
I think the problem maybe that you suppose that every user has only one consumer while this is not correct regarding data.
I had the same problem and it was because the relationship was on-to-many and I made it one-to-one.

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");
}