How to use auto increment id with Entitiy Framework 6 and PostgreSQL not EF CORE? - postgresql

I have MVC Framework Project with EF6 and POSTGRESQL. I'm using database first and create edmx file from database.
public partial class MinimalEarthEntities : DbContext
{
public MinimalEarthEntities()
: base("name=MinimalEarthEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<User> User { get; set; }
}
public partial class User
{
public long Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string GSM { get; set; }
public string Password { get; set; }
}
These code was generated from EF6. ID column is auto increment value. But EF6 can not be instert data due to auto increment not working.
Is there anybody help to solve this problem?

Related

How do I fix this SQLite error: SQLite Error 1: 'table "StudentCourses" already exists'

I'm creating a CRUD project in asp.net entity framework, and from my understanding, in order to see the data on the HTML page I have to scaffold the pages. For example I have two entity models Student and Major
This is the Student entity
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Major")]
public int? MajorId { get; set; }
public Major Major { get; set; }
[ForeignKey("Advisor")]
public int AdvisorId { get; set; }
public Advisor Advisor { get; set; }
public ICollection<StudentCourses>? StudentCourses { get; set; }
}
This is the Major entity
public class Major
{
public int MajorId { get; set; }
public string MajorName { get; set; }
public ICollection<Student> Students { get; set; }
public ICollection<Advisor> Advisors { get; set; }
public ICollection<MajorCourse> MajorCourses { get; set; }
}
If I want to see the Student data I have to create a Students folder and add a new Scaffolding along with a DbContext like your_namespace.Data.StudentContext. I would also have to follow the same steps for the Major entity but am I correct to use another DbContext? For example: your_namespace.Data.MajorContext. This is what I have done but when I try to make migrations and update the database in the your_namespace.Data.MajorContext, I get an error that reads SQLite Error 1: 'table "StudentCourses" already exists'.`
How do I fix this error?
I should also add the Context classes:
This is the StudentContext class:
public class AdvismentContext : DbContext
{
public AdvismentContext(DbContextOptions<AdvismentContext> options)
: base(options)
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Major> Majors { get; set; }
public DbSet<Advisor> Advisors { get; set; }
public DbSet<Course> Courses { get; set; }
public DbSet<MajorCourse> MajorCourses { get; set; }
public DbSet <StudentCourses> StudentCourses{ get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.ToTable("Students");
modelBuilder.Entity<Major>()
.ToTable("Majors");
modelBuilder.Entity<Advisor>()
.ToTable("Advisors");
modelBuilder.Entity<Course>()
.ToTable("Courses");
//modelBuilder.Entity<MajorCourse>()
// .ToTable("MajorCourse");
//.HasKey(mc => new { mc.MajorId, mc.CourseId });
}
And this is the MajorContext class:
public class MajorContext : DbContext
{
public MajorContext (DbContextOptions<MajorContext> options)
: base(options)
{
}
public DbSet<Advisment.Models.Major> Major { get; set; } = default!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Major>()
.ToTable("Major");
//modelBuilder.Entity<MajorCourse>() This is commented out because I was getting the same error that the table already exists.
// .ToTable("MajorCourse");
}
}
What am I doing wrong?

NullReferenceException on join with Postgres EF Provider

I have a postgres database and using asp.net core mvc (+ ef). The database is created correctly. I have two tables 'Module' and 'ModuleMenu'. I want to get all the menu's for a given module but I keep on failing to create the linq query.
Situation
Model: Module.cs
namespace project.Model
{
public class Module
{
[Required]
public string ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
}
}
Model: ModuleMenu.cs
namespace project.Models
{
public class ModuleMenu
{
[Required]
public string ID { get; set; }
public int ModuleID { get; set; }
[Required]
public string Title { get; set; }
[ForeignKey("ModuleID")]
public virtual Module Module { get; set; }
}
}
ApplicationDbContext.cs
namespace project.Data
{
public class ApplicationDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
public DbSet<Module> Modules { get; set; }
public DbSet<ModuleMenu> ModuleMenus { get; set; }
}
}
Query
public List<ModuleMenu> GetModuleMenus(){
var query = from m in _dbContext.ModuleMenus
join mod in _dbContext.Modules on
m.ModuleID equals mod.ID
select m;
return query.ToList();
}
Error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
An exception was thrown attempting to execute the error handler.
System.NullReferenceException: Object reference not set to an instance of an object.
Can anyone help me to correctly create the query?
Is this part correct in your code?
public int ModuleID { get; set; }
It seems that you might have had an error in the type used for the fk.
Below I changed the type to be string rather than int.
public string ModuleID { get; set; }
based on that update, the query could look like this.
public ModuleMenu[] GetModuleMenusForModule(string moduleId)
{
return _dbContext.ModuleMenus.Where(x => x.ModuleID == moduleId).ToArray();
}
I would expect that model to error (ModelID and ID are incompatible types). If that were correct, your code should work. Or simpler:
public List<ModuleMenu> GetModuleMenus()
{
return _dbContext.ModuleMenus.ToList();
}

EF code first telling me to do the migration for db object which is already is in db

i am working with EF code first. so initially i have no tables in database. so i wrote some class and when query those class then i saw EF code first create those tables in db but when i create sql server view in db and later map that view with my code in c# & EF project and when i try to query that view then i was getting error message as follows.
Additional information: The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database
i understand that EF is telling me to do the migration but if i migrate then EF will create that view in db again when the view is in db already exist.
so tell me how could i inform EF that my view is already is in db so migration is not required.
please guide me. thanks
EDIT 1
first time my database has no table. so i wrote some classes like below one.
public class CustomerBase
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
}
public class Customer : CustomerBase
{
public virtual List<Addresses> Addresses { get; set; }
}
public class Addresses
{
[Key]
public int AddressID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public bool IsDefault { get; set; }
public virtual List<Contacts> Contacts { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
}
public class Contacts
{
[Key]
public int ContactID { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public bool IsDefault { get; set; }
public int AddressID { get; set; }
public virtual Addresses Customer { get; set; }
}
public class TestDBContext : DbContext
{
public TestDBContext()
: base("name=TestDBContext")
{
}
public DbSet<Customer> Customer { get; set; }
public DbSet<Addresses> Addresses { get; set; }
public DbSet<Contacts> Contacts { get; set; }
}
when i query the customer like below query then EF create all required tables in db behind the curtains.
var bsCustomer = (from cu in db.Customer
where (cu.CustomerID == 2)
select new
{
cu,
Addresses = from ad in cu.Addresses
where (ad.IsDefault == true)
from ct in ad.Contacts
select ad,
}).ToList();
later i create a view in db and refer that view in code like below one.
public partial class vwCustomer
{
[Key]
public int CustomerID { get; set; }
public string FirstName { get; set; }
}
public class vwCustomerConfiguration : EntityTypeConfiguration<vwCustomer>
{
public vwCustomerConfiguration()
{
this.HasKey(t => t.CustomerID);
this.ToTable("vwCustomers");
}
}
so now my DbContext look like below one with view class reference
public class TestDBContext : DbContext
{
public TestDBContext()
: base("name=TestDBContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new vwCustomerConfiguration());
}
public DbSet<Customer> Customer { get; set; }
public DbSet<Addresses> Addresses { get; set; }
public DbSet<Contacts> Contacts { get; set; }
public virtual DbSet<vwCustomer> vwCustomers { get; set; }
}
Error occur the moment i try to query the view
using (var db = new TestDBContext())
{
var listMyViews = db.vwCustomers.ToList();
}
the error was Additional information: The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database
thanks
Another way we can do it and it solve my problem. see the code.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}
code taken from here https://stackoverflow.com/a/6143116/6188148
we can follow this approach too.
public partial class AddingvwCustomer : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
i guess this will works too but not tested myself.
we can use the Fluent API to configure it using the Ignore method:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Ignore<MyClass>();
}
Add new migration as normally and from the migration code in Up (and Down) method remove code that tries to create new table manually (call to CreateTable method in Up and DropTable in Down). Then apply migration to your db and everything works perfectly.
Unfortunately automatic migration generation is not very intelligent tool and very often one need to manually specify how the database should be altered. In the documentation for EF migrations it is stated that it is perfectly fine to edit manually migrations code.

Entity Framework Navigation Property Error

I am getting this error in my .Net MVC 4 web application:
The property 'Username' cannot be configured as a navigation property. The
property must be a valid entity type and the property should have a non-abstract
getter and setter. For collection properties the type must implement
ICollection<T> where T is a valid entity type.
I am very new to Entity Framework and I can't seem to get around this issue. Here is some code:
//DB Context
public class EFDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(u => u.Roles).WithMany(r => r.Users).Map(x => x.MapLeftKey("Username").MapRightKey("RoleName").ToTable("Users_Roles"));
}
}
//Entity Classes
public class User
{
[Key]
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Comment { get; set; }
public int Level { get; set; }
public string PasswordQuestion { get; set; }
public string PasswordAnswer { get; set; }
public bool IsApproved { get; set; }
public DateTime LastActivityDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangedDate { get; set; }
public DateTime CreationDate { get; set; }
public bool IsOnLine { get; set; }
public bool IsLockedOut { get; set; }
public DateTime LastLockedOutDate { get; set; }
public int FailedPasswordAttemptCount { get; set; }
public DateTime FailedPasswordAttemptWindowStart { get; set; }
public int FailedPasswordAnswerAttemptCount { get; set; }
public DateTime FailedPasswordAnswerAttemptWindowStart { get; set; }
[InverseProperty("RoleName")]
public virtual ICollection<Role> Roles { get; set; }
public override string ToString()
{
return this.Username;
}
}
public class Role
{
[Key]
public string RoleName { get; set; }
public int Level { get; set; }
[InverseProperty("Username")]
public virtual ICollection<User> Users { get; set; }
public override string ToString()
{
return this.RoleName;
}
}
//Repository
public class EFUsersRepository : IUsersRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<User> Users
{
get { return context.Users; }
}
public User GetUser(string username)
{
return context.Users.Find(username); //THIS IS WHERE THE CRASH OCCURS
}
}
//DB Setup
Table Users, Role and Users_Role. Users_Role is a simple linking table with [username, role] columns both of type varchar.
The database tables columns & types match the two classes above (User,Role).
I inherited this project which was unfinished but I can't get it to run successfully. Any help understanding what the issue is would be helpful. Thanks!
It might be that Entity Framework is updated. Easiest way will be to recreate the DataModel.
Even if the previous programmer did not use Entity Data Mode, you can at least copy the auto generated code such as EFDbContext, Users and Roles classes.
It turns out, after commenting out enough items all day long, the the following lines are what caused this error for me:
[InverseProperty("RoleName")] //In file User.cs (as shown above)
[InverseProperty("UserName")] //in file Role.cs (as shown above)
I am still learning Entity Framework and I don't know why this was the solution, but it stopped the error which I reported above.
I hope that this helps someone else and if anyone wants to help me understand what the issue was in detail, please feel free. I am eager to learn.

EF Code First: Treating entity like a complex type (denormalization)

I'm using EF 4.1 Code First, and I'm making a configurable utility for parsing/importing large delimited files. Each row in the file may contain data for several entities.
The exact data and layout for the file will be unknown at build time (it's configured differently for each client), so I'm making it configurable.
Example model (simplified)
public class Contact {
public int Id { get; set;}
public string Name { get; set; }
}
public class Account {
public int Id { get; set; }
public decimal Balance { get; set; }
public bool IsOpen { get; set; }
}
Depending on the client, a file may contain contact info, account info, or both. Because of the size of these files (tons of records), we have to use SqlBulkCopy to do the data loading. It's also unknown at compile time exactly what rules will be run against the data (validation changes by client, etc.)
I want to have a table and class, like ImportRecord, to hold the imported data. My current working class is like:
public class ImportRecord {
public string Contact_Name { get; set; }
public decimal Account_Balance { get; set; }
public bool Account_IsOpen { get; set; }
}
The issue here is that as we add/change fields in the model classes, the ImportRecord has to get changed also -- it's duplicative/less than ideal. It's somewhat important to me that the import data resides in a single table to simplify the SqlBulkCopy import.
My ideal ImportRecord class would look like this:
public class ImportRecord {
public Contact Contact { get; set; }
public Account Account { get; set; }
}
But that would just create a table with two foreign keys (aside from complaining about no FK properties). Is there a way to have the entity classes behave more like a denormalized, keyless, complex type for the ImportRecord? Am I going about this entirely wrong?
Thanks!
Entity cannot be nested and in the same time complex type cannot have entity key so you cannot use one instead of other but you can try this little cheat. I just tested that it at least creates correct database structure:
public class Context : DbContext
{
public DbSet<Account> Accounts { get; set; }
public DbSet<Contact> Contacts { get; set; }
public DbSet<ImportRecord> ImportRecords { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ComplexType<ContactBase>();
modelBuilder.ComplexType<AccountBase>();
}
}
public class ContactBase
{
public string Name { get; set; }
}
public class AccountBase
{
public decimal Balance { get; set; }
public bool IsOpen { get; set; }
}
public class Contact : ContactBase
{
public int Id { get; set; }
}
public class Account : AccountBase
{
public int Id { get; set; }
}
public class ImportRecord
{
public int Id { get; set; }
public ContactBase Contact { get; set; }
public AccountBase Account { get; set; }
}