it's been a while since I work with EntityDataModel. I used to do things like:
var listaProductos = dbContext.Productos.Select(p => new
I just started a new web project with asp.net and added the entity data model but If i try to do the same as the example above I can't use ".Select". Do I need to install any Nuget package or something?
I work with Visual Studio 2013.
Thanks for your help.
You should add namespase to your file:
using System.Linq;
check your namespace and dbContext class.
Like
using ContosoUniversity.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace ContosoUniversity.DAL
{
public class SchoolContext : DbContext
{
public SchoolContext() : base("SchoolContext")
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
Related
I'm building an ASP.NET Web Api with simple CRUD operations and a Database which should be generated using EF Code First and Migrations.
In terms of the structure of the project, I am using ASP.NET Web API as the main project and a class library as the database context.
This is what I have in my Class library:
Database Context:
using Microsoft.EntityFrameworkCore;
using MyApp.Database.Models;
namespace MyApp.Database.Context;
public class MyAppContext : DbContext
{
public MyAppContext(DbContextOptions<MyAppContext> options) : base(options) { }
public virtual DbSet<Booking> Bookings { get; set; }
public virtual DbSet<Person> Persons { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Seed();
base.OnModelCreating(modelBuilder);
}
}
Database Models:
namespace MyApp.Database.Models;
public class Booking
{
public int Id { get; set; }
public int Week { get; set; }
public int DayOfWeek { get; set; }
public int Hour { get; set; }
public int PersonId { get; set; }
public virtual Person Person { get; set; }
}
using System.Collections.Generic;
namespace MyApp.Database.Models;
public class Person
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Age { get; set; }
public virtual IEnumerable<Booking> Bookings { get; set; }
}
Besides that I have a class in the library called SeederExtension which has an Extension method that should Seed the database
using Microsoft.EntityFrameworkCore;
using MyApp.Database.Models;
namespace MyApp.Database;
public static class SeedExtension
{
public static void Seed(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().HasData(new Person
{
Id = 1,
Firstname = "John",
Lastname = "Doe",
Age = 28,
});
}
}
In my ASP.NET Web API project I register the Database context in my Program.cs with the following code.
builder.Services.AddDbContext<MyAppContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("MyAppDb"));
});
The problem is now when I want to add migrations. I go to the Package Manager Console and navigate to the Class Library project where my Database Context is located.
Then I enter this command to add a migration:
dotnet ef migrations add "Init"
which produces this error then:
Unable to create an object of type 'MyAppContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
I've seen a lot of tutorial where this worked but unfortunately after hours of research I haven't found a working solution.
I'm using .net6 and the following NuGet packages in my class library
Microsoft.EntityFrameworkCore (version 7.0.2)
Microsoft.EntityFrameworkCore.SqlServer (version 7.0.2)
Microsoft.EntityFrameworkCor.Tools (version 7.0.2)
And here is my connectionString if it helps:
{
"ConnectionStrings": {
"MyAppDb": "server=(LocalDB)\\mssqllocaldb;database=MyAppDB;integrated security=True"
}
}
Try adding a parameterless constructor: public MyAppContext() {}.
Options are to pass to constructor by DI based on your ConfigureService in the Startup class. 'Add migration' shouldn't know what options to pass since it does not use the Startup.
If you take a look at here
https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/projects?tabs=dotnet-core-cli
Note the difference in your command and selecting the database csproj. In the docs it has:
dotnet ef migrations add NewMigration --project WebApplication1.Migrations
The connection string comes from your main project. Again, from the docs:
services.AddDbContext<ApplicationDbContext>(
options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("WebApplication1.Migrations")));
I have, obviously, just pasted in the above from the docs. You will need to match with your own projects.
If you instead run the migrations using just the database project, I am not sure it would pick up the connection string out the web api project.
I'm working in a Entity Framework + SQLite app, and i don't know how activate PRAGMA foreign_keys = 1 in the Model for C# application.
Here my model (My_model.Context.cs)
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class My_Model : DbContext
{
public My_Model()
: base("name=My_Model")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<My_TABLE1> My_TABLE1 { get; set; }
public virtual DbSet<My_TABLE2> My_TABLE2 { get; set; }
public virtual DbSet<My_TABLE3> My_TABLE3 { get; set; }
public virtual DbSet<My_TABLE4> My_TABLE4 { get; set; }
}
Any idea?
I have tried modify App.conf doesn't works.
I have found many examples but no works for me.
In your App.Config file, add "foreign keys=true" to the connection string, like this:
data source=c:\wherever\whatever.sqlite;DateTimeFormat=InvariantCulture;foreign keys=true
Presently, I am attempting to use Effort (https://effort.codeplex.com/) with my Entity Framework 6 solution to allow unit testing without requiring a database connection (see http://www.codeproject.com/Articles/460175/Two-strategies-for-testing-Entity-Framework-Effort). Everything works in my project, where this is the DbContext with an interface and the overloaded constructors required for Effort:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class HRADDbContext : DbContext, IHRADDbContext
{
public HRADDbContext() : base("name=HRADDbContext")
{
}
public HRADDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}
public HRADDbContext(DbConnection connection)
: base(connection, true)
{
this.Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
The problem is, if I update the .edmx file by choosing "Update model from database..." then it regenerates the context file to be:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Common;
using System.Data.Entity;
public partial class HRADDbContext : DbContext
{
public HRADDbContext() : base("name=HRADDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
So I have to go back and manually update the above Context.cs file every time. Also, removes the [Key] from the POCO CCS_DEPT_TBL file.
Is there any way to setup my Entity Framework project so that it doesn't blow away the interface and overloaded constructors every time I update the model from the database? TIA.
UPDATE:
Since the class is partial, I just ensure that the interface and overloaded constructors are put in a separate file that is not auto-generated.
UPDATE 2:
OK, got it, just added this as a separate file, taking the DEPTID out of the original POCO file, but it still puts that DEPTID in the generated file, so after an update the build breaks because there are two DEPTID values in the same class:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class CCS_DEPT_TBL
{
[Key]
public string DEPTID { get; set; }
}
}
So, how do I prevent it from generating DEPTID in the generated class file, since it is already in the above partial class file?
Yes, the class is defined as a partial class. Create a new file that also declares the same partial class and add your additional methods there.
As for the [Key] attribute being lost, you can try and use a MetadataType attribute and put all your meta data there.
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(CCS_DEPT_TBL_Meta))]
public partial class CCS_DEPT_TBL
{
... Your additional constructors and methods here ...
}
public class CCS_DEPT_TBL_Meta
{
[Key]
public string DEPTID { get; set; }
}
}
Thank you #Robert McKee! Here is what I ended up doing:
CCS_DEPT_TBL_Key.cs:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[MetadataType(typeof(CCS_DEPT_TBL_Meta))]
public partial class CCS_DEPT_TBL
{
}
public class CCS_DEPT_TBL_Meta
{
[Key]
public string DEPTID { get; set; }
}
}
CCS_DEPT_TBL.cs:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
public partial class CCS_DEPT_TBL
{
// This table in SQL Server does not have a primary key, it just has an index
public string DEPTID { get; set; }
public string DESCR { get; set; }
public System.DateTime EFFDT { get; set; }
public string EFF_STATUS { get; set; }
public Nullable<System.DateTime> LASTUPDDTTM { get; set; }
}
}
HRModel.Context.cs: The HRADDbContext is actually database-first entities, but there are three other *.edmx files that are code-first entities in the same project, so commented out this exception in HRModel.Context.cs because it doesn`t apply. It would probably be better to separate out the database-first entities into a separate project so this exception would not be generated on a database model update.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class HRADDbContext : DbContext
{
public HRADDbContext()
: base("name=HRADDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
HRADDbContext.cs, where the IHRADDbContext interface is necessary for Effort:
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
/// <summary>
/// Added interface here so that it does not get removed when updating
/// model from the database on code generation.
/// </summary>
partial class HRADDbContext : IHRADDbContext
{
public HRADDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}
public HRADDbContext(DbConnection connection)
: base(connection, true)
{
this.Configuration.LazyLoadingEnabled = false;
}
}
}
I am new to MVC and C#. I just stumbled on it and found it interesting. I encountered an issue which will not allow me proceed.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyHotel.Models
{
public class AccountTypes
{
public int AccountTypeID { get; set; }
public string AccountTypeName { get; set; }
}
}
I created the controler and the view thereafter.
And for this, I keep got this error:
One or more validation errors were detected during model generation:
System.Data.Edm.EdmEntityType: : EntityType 'AccountTypes' has no key defined. Define the key for this EntityType.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet "AccountTypes" is based on type "AccountTypes" that has no keys defined.
I google that the answers were to add [Key] over the public int AccountTypeID { get; set; } so it could look like this:
namespace MyHotel.Models
{
public class AccountTypes
{
[Key]
public int AccountTypeID { get; set; }
public string AccountTypeName { get; set; }
}
}
But no result until now.
Note: I am using MVC 4
Description
Entity Framework CodeFirst recognize the key, by default, by name.
Valid names are Id or <YourClassName>Id.
Your property should named Id or AccountTypesId
Another way is to use the ModelBuilder to specify the key.
Sample
public class MyDbContext : DbContext
{
public DbSet<AccountTypes> AccountTypes { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountTypes>.HasKey(x => x.AccountTypeID);
base.OnModelCreating(modelBuilder);
}
}
Mode Information
Entity Framework Code First Tutorial
Try using [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] property to indicate the key field.
The regular field would go with EntityKeyPropert=false.
public class MyDbContext : DbContext
{
public DbSet<AccountTypes> AccountTypes { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountTypes>().HasKey(x => x.AccountTypeID);
base.OnModelCreating(modelBuilder);
}
}
Hi Peter it seens you are missing an "s"
Your Account int should be:
public int AccountsTypeID { get; set; }
Hope it can be solved; Fernando.
I am using the Microsoft Entity Framework with code first to manage my data (with MySQL). I have defined a POCO object, however, when I try to add data it says table Users doesn't exist. I looked in the DB and it created table User not Users. How can I remedy this? It is driving me nuts!
Thanks!
public class User
{
[Key,Required]
public int UserId { get; set; }
[StringLength(20), Required]
public string UserName { get; set; }
[StringLength(30), Required]
public string Password { get; set; }
[StringLength(100), Required]
public string EmailAddress { get; set; }
[Required]
public DateTime CreateDate { get; set; }
[Required]
public bool IsActive { get; set; }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace YourNamespace
{
public class DataContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<User> User { get; set; }
}
}
I have not used MySQL with EF yet but regardless I think the solution is unbias. You need to turn off Pluralize Table Convention.
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions.Edm.Db;
public class MyDbContext: DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Now EF will look for the literal of your object name to the table name.
Some great video tutorials are at http://msdn.microsoft.com/en-us/data/aa937723 under the Continue Learning Entity Framework. For additional learning experience, you can not specify the above but rather explicitly map the object 'user' to the table 'user'.
Additional References:
http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx
You can put an attribute on the class telling the name of the table:
[Table("Users")]
public class User
{
//...
}
...or you could use the fluent API. To do this you will override the OnModelCreating method in your DbContext class.
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Map(t => t.ToTable("Users"));
}
}
In future versions of EF, we've been promised the ability to write our own conventions. Thats not in there yet as of version 4.1...
(Haven't tried it with MySQL...)