.NET Core 5.0 EF Migration add new foreign column - asp.net-mvc

I have an application with .net core Entity Framework code first.
I have 2 tables in relationships.
altKategori and anaKategori
altKategoris
public class altKategori
{
[Key]
public int idAltKategori { get; set; }
[Column(TypeName = "Varchar")]
[StringLength(30)]
public string adAltKategori { get; set; }
public int idAnaKategori { get; set; }
public anaKategori anaKategori { get; set; }
}
anaKategoris
public class anaKategori
{
[Key]
public int idAnaKategori { get; set; }
[Column(TypeName = "Varchar")]
[StringLength(30)]
public string adAnaKategori { get; set; }
public List<altKategori> altKategoris { get; set; }
}
Also there is my Context:
public class Context : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.\\MSSQLSERVER2019;database=deneme;User ID=deneme1;Password=****;");
}
public DbSet<altKategori> altKategoris { get; set; }
public DbSet<anaKategori> anaKategoris { get; set; }
}
When I start migration, migration automatic add anaKategoriidAnaKategori columns, and add relationship with that column.
migrationBuilder.CreateTable(
name: "altKategoris",
columns: table => new
{
idAltKategori = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
adAltKategori = table.Column<string>(type: "Varchar(30)", maxLength: 30, nullable: true),
idAnaKategori = table.Column<int>(type: "int", nullable: false),
anaKategoriidAnaKategori = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_altKategoris", x => x.idAltKategori);
table.ForeignKey(
name: "FK_altKategoris_anaKategoris_anaKategoriidAnaKategori",
column: x => x.anaKategoriidAnaKategori,
principalTable: "anaKategoris",
principalColumn: "idAnaKategori",
onDelete: ReferentialAction.Restrict);
});
I don't want to relation with anaKategoriidAnaKategori. I want to relation with idAnaKategori. How can I?
Thanks for your help.

try to add relation attributes
public class altKategori
{
[Key]
public int idAltKategori { get; set; }
[Column(TypeName = "Varchar")]
[StringLength(30)]
public string adAltKategori { get; set; }
public int idAnaKategori { get; set; }
[ForeignKey(nameof(idAnaKategori ))]
[InverseProperty("altKategoris")]
public anaKategori anaKategori { get; set; }
}
public class anaKategori
{
[Key]
public int idAnaKategori { get; set; }
[Column(TypeName = "Varchar")]
[StringLength(30)]
public string adAnaKategori { get; set; }
[InverseProperty(nameof(altKategori.anaKategori))]
public List<altKategori> altKategoris { get; set; }
}

Related

AutoMapper Many to Many relationship

I'm not sure where I'm going wrong here. I want to map my classes so that there aren't extra levels in the returned values.
Models (DTOs):
public class FilmViewModel
{
public FilmViewModel() { }
public int Id { get; set; }
[Required(ErrorMessage = "Naziv filma je obavezno polje.")]
public string Naziv { get; set; }
public string Opis { get; set; }
public string UrlFotografije { get; set; }
[RegularExpression(#"^(19|20)[\d]{2,2}$", ErrorMessage = "Godina mora biti u YYYY formatu.")]
public int Godina { get; set; }
public JezikEnum Jezik { get; set; }
public int Trajanje { get; set; }
public bool IsActive { get; set; }
public List<Licnost> Licnosti { get; set; }
}
public class LicnostViewModel
{
public LicnostViewModel() { }
public int Id { get; set; }
[Required]
public string ImePrezime { get; set; }
[Required]
public bool IsGlumac { get; set; }
[Required]
public bool IsRedatelj { get; set; }
public List<Film> Filmovi { get; set; }
}
Entities:
public class Film
{
[Key]
public int Id { get; set; }
[Required]
public string Naziv { get; set; }
public string Opis { get; set; }
public string UrlFotografije { get; set; }
[RegularExpression(#"^(19|20)[\d]{2,2}$")]
public int Godina { get; set; }
public JezikEnum Jezik { get; set; }
public bool IsActive { get; set; }
public int Trajanje { get; set; }
public List<FilmLicnost> Licnosti { get; set; }
}
public class Licnost
{
[Key]
public int Id { get; set; }
[Required]
public string ImePrezime { get; set; }
[Required]
public bool IsGlumac { get; set; }
[Required]
public bool IsRedatelj { get; set; }
public List<FilmLicnost> Filmovi { get; set; }
}
public class FilmLicnost
{
[Key]
public int Id { get; set; }
[ForeignKey(nameof(Licnost))]
public int LicnostId { get; set; }
public Licnost Licnost { get; set; }
[ForeignKey(nameof(Film))]
public int FilmId { get; set; }
public Film Film { get; set; }
}
Basically Swagger already shows me what I'm returning, but I want to avoid unnecessary nesting. It's marked in the image:
I want to say that I've been looking all over SO, AutoMapper documentation etc. No answer/example finds me the solution I need. I'm either missing a Model(DTO) somewhere or there is something major wrong with my logic.
Some example links that I tried are this and this
Also here are some links I tried to get information from: link1, link2
This is what I've tried so far:
CreateMap<FilmLicnost, LicnostViewModel>()
.ForMember(dest => dest.Filmovi, dest => dest.MapFrom(x => x.Film))
.AfterMap((source, destination) =>
{
if (destination?.Filmovi == null) return;
foreach (var temp in destination.Filmovi)
{
temp.Id = source.Film.Id;
temp.IsActive = source.Film.IsActive;
temp.Jezik = source.Film.Jezik;
temp.Naziv = source.Film.Naziv;
temp.Opis = source.Film.Opis;
temp.Godina = source.Film.Godina;
temp.Trajanje = source.Film.Trajanje;
temp.UrlFotografije = source.Film.UrlFotografije;
}
});
CreateMap<FilmLicnost, FilmViewModel>()
.ForMember(dest => dest.Licnosti, dest => dest.MapFrom(x => x.Licnost))
.AfterMap((source, destination) =>
{
if (destination?.Licnosti == null) return;
foreach (var temp in destination?.Licnosti)
{
temp.Id = source.Licnost.Id;
temp.ImePrezime = source.Licnost.ImePrezime;
temp.IsGlumac = source.Licnost.IsGlumac;
temp.IsRedatelj = source.Licnost.IsRedatelj;
}
});
Also this:
CreateMap<FilmLicnost, Film>()
.ForMember(dest => dest.Licnosti, dest => dest.Ignore());
CreateMap<FilmLicnost, Licnost>()
.ForMember(dest => dest.Filmovi, dest => dest.Ignore());
Note I have already defined the mapping for Entities:
CreateMap<Film, FilmViewModel>();
CreateMap<FilmViewModel, Film>();
CreateMap<Licnost, LicnostViewModel>();
CreateMap<LicnostViewModel, Licnost>();

Table Value Function mapping with Entity Framework 6.3

How do I map table value functions in Code with Entity Framework 6.3? I'm trying to a DB Context in code with an existing database, because EDMX is currently not supported in ASP.NET Core 3. I've tried setting up my DbContext clasee as below. I can successfully query the Grade table. But when I try to query my function "fn_GetCatgeories", I get the following error: No EdmType found for type 'WebApplication6.Data.ApplicationContext+fn_GetCategories'.
public class ApplicationContext : DbContext
{
public ApplicationContext(string cstr)
: base(cstr)
{
Database.SetInitializer<ApplicationContext>(null);
}
[Table("Grade")]
public class Grade
{
[Key]
public string Grade_ID { get; set; }
public string SchoolType { get; set; }
public int Sortorder { get; set; }
}
public partial class fn_GetCategories
{
public int Category_ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Nullable<bool> Active { get; set; }
public Nullable<System.DateTime> Month { get; set; }
public Nullable<int> Order { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new FunctionsConvention<ApplicationContext>("dbo"));
base.OnModelCreating(modelBuilder);
}
[DbFunction("ApplicationContext", "fn_GetCategories")]
public IQueryable<fn_GetCategories> GetCategories(Nullable<System.DateTime> month)
{
var monthParameter = month.HasValue ?
new ObjectParameter("Month", month) :
new ObjectParameter("Month", typeof(System.DateTime));
return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<fn_GetCategories>(string.Format("[0].{1}", GetType().Name, "[fn_GetCategories](#Month)"), monthParameter);
}
// DbSets here
public DbSet<Grade> Grades { get; set; }
}
This works:
public class ApplicationContext : DbContext
{
public ApplicationContext(string cstr)
: base(cstr)
{
Database.SetInitializer<ApplicationContext>(null);
}
[Table("Grade")]
public class Grade
{
[Key]
public string Grade_ID { get; set; }
public string SchoolType { get; set; }
public int Sortorder { get; set; }
}
public partial class fn_GetCategories_Result
{
[Key]
public int Category_ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Nullable<bool> Active { get; set; }
public Nullable<System.DateTime> Month { get; set; }
public Nullable<int> Order { get; set; }
}
// DbSets here
public DbSet<Grade> Grades { get; set; }
public DbSet<fn_GetCategories_Result> fn_GetCategoriesSet { get; set; }
public List<fn_GetCategories_Result> fn_GetCategories(DateTime month)
{
var m = new SqlParameter("Month", DateTime.Now);
return this.fn_GetCategoriesSet.SqlQuery("select * from dbo.fn_GetCategories(#month)", m).ToList();
}

Seed data in code first Entity Framework

I am using code-first Entity Framework in my ASP.NET MVC project
I have these tables
User
public class User:IBaseEntity
{
public User()
{
UserRoles = new List<UserRole>();
}
public int ID { get; set; }
public int RoleId { get; set; }
public string Email { set; get; }
public string Password { set; get; }
public string FirstName { set; get; }
public string LastName { set; get; }
public string Company { set; get; }
public string Address1 { set; get; }
public string Address2 { set; get; }
public string City { set; get; }
public string PostalCode { set; get; }
public string Country { set; get; }
public string State { set; get; }
public bool Active { set; get; }
public DateTime? CreatedOn { set; get; }
public DateTime? DeletedOn { set; get; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
Role
public class Role : IBaseEntity
{
public int ID { get; set; }
public string RoleName { get; set; }
public bool Active { set; get; }
public DateTime? CreatedOn { set; get; }
public DateTime? DeletedOn { set; get; }
}
UserRole
public class UserRole : IBaseEntity
{
public int ID { get; set; }
public int UserId { get; set; }
public int RoleId { get; set; }
public virtual Role Role { get; set; }
}
IBaseEntity
public interface IBaseEntity
{
int ID { get; set; }
}
I need seed data User with UserRole
How can I put UserRole in method create User?
public void CreateRoles(CMSDbContext context)
{
if (context.Roles.Count() == 0)
{
List< Role> listRole = new List<Role>()
{
new Role()
{
RoleName = "Admin",
Active = true,
CreatedOn = DateTime.Now
},
new Role()
{
RoleName = "User",
Active = true,
CreatedOn = DateTime.Now
}
};
context.Roles.AddRange(listRole);
context.SaveChanges();
}
}
public void CreateUser(CMSDbContext context)
{
if (context.Users.Count() == 0)
{
List<User> listUser = new List<User>()
{
new User()
{
FirstName = "David",
LastName = "Lima",
Active = true,
Email = "admin#domain.com",
Address1 = "New York",
Address2 = "Chicago",
Company = "Test",
CreatedOn = DateTime.Now,
PostalCode = "123456",
State = "Test",
City = "test",
UserRoles =???
Password = CMS.Common.HashMD5.CreateMD5("12356")
}
};
context.Users.AddRange(listUser);
context.SaveChanges();
}
}
}
Please focus on method CreateUser have property UserRole, not sure what I can put here. I also create some roles in Role table (admin, user)
I am getting stuck at this point.
Any help will be appreciated
Thanks all

Need two separate tables but EF 6 is creating only one

I have a Contractor class and a Musicians Class which inherits the Contractor class. I am running migration and it will only build one Contractor table with Musicians fields included. I want a Contractor table and Musicians table that follows my domain models. It creates Instrument table correctly. Does this have something to do with the fact I am using inheritance on the classes?
public class Contractor
{
public Guid ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string ZipCode { get; set; }
public string Phone { get; set; }
public string Description { get; set; }
[DataType(DataType.Date)]
public DateTime CreateDate { get; set; }
[DataType(DataType.Date)]
public DateTime SuspendDate { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
public string ImageName { get; set; }
public bool Suspended { get; set; }
}
public class Musician : Contractor
{
public Guid MusiciansId { get; set; }
public string WebsiteLink { get; set; }
public string YouTubeLink { get; set; }
public string SoundCloudLink { get; set; }
public string ReverbNationLink { get; set; }
public int YearsOfExperience { get; set; }
[DataType(DataType.Date)]
public DateTime NextDateAvailable { get; set; }
public Instrument Instrument { get; set; }
public int InstrumentId { get; set; }
public Contractor Contractor { get; set; }
public Guid ContractorId { get; set; }
}
My Migration script :
CreateTable(
"dbo.Contractor",
c => new
{
ID = c.Guid(nullable: false),
FirstName = c.String(),
LastName = c.String(),
Email = c.String(),
ZipCode = c.String(),
Phone = c.String(),
Description = c.String(),
CreateDate = c.DateTime(nullable: false),
SuspendDate = c.DateTime(nullable: false),
ImageData = c.Binary(),
ImageMimeType = c.String(),
ImageName = c.String(),
Suspended = c.Boolean(nullable: false),
UnionMember = c.Boolean(),
MusiciansId = c.Guid(),
WebsiteLink = c.String(),
YouTubeLink = c.String(),
SoundCloudLink = c.String(),
ReverbNationLink = c.String(),
YearsOfExperience = c.Int(),
NextDateAvailable = c.DateTime(),
InstrumentId = c.Int(),
ContractorId = c.Guid(),
Discriminator = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => t.ID)
.ForeignKey("dbo.Contractor", t => t.ContractorId)
.ForeignKey("dbo.Instrument", t => t.InstrumentId, cascadeDelete: true)
.Index(t => t.InstrumentId)
.Index(t => t.ContractorId);
It is not a good idea to use inheritance in model classes.
You can add Type value for your Contractor and create another table for each type of contractor (Musician for example):
public enum ContractorType
{
Musician = 0
}
public class Contractor
{
public Guid ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string ZipCode { get; set; }
public string Phone { get; set; }
public string Description { get; set; }
[DataType(DataType.Date)]
public DateTime CreateDate { get; set; }
[DataType(DataType.Date)]
public DateTime SuspendDate { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
public string ImageName { get; set; }
public bool Suspended { get; set; }
public ContractorType contractorType { get; set; }
public Musician Musician { get; set; }
}
After doing some research the answer is: [Table] attribute above Musicians class.
http://www.codeproject.com/Articles/796521/Inheritance-in-Entity-Framework-Table-Per-Type

Automapper mapping issue

I need to map a model to a viewmodel using AutoMapper.
Model:
[Table("News")]
public class News
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public DateTime DatePostedOn { get; set; }
public int Position { get; set; }
public Category Category { get; set; }
public virtual ICollection<Picture> Pictures { get; set; }
}
[Table("Pictures")]
public class Picture
{
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public string Filename { get; set; }
public int Type { get; set; }
public virtual ICollection<News> News { get; set; }
}
Viewmodel:
public class HomeViewModels
{
public IList<HomeMainNews> MainNews { get; private set; }
}
public class HomeMainNews
{
public int Id { get; set; }
public string Title { get; set; }
public string Date { get; set; }
public string PictureURL { get; set; }
}
Mapping:
Mapper.CreateMap<News, HomeMainNews>();
How can I map a News that have a set of Pictures, to a viewmodel with only one picture according to a certain condition "Type = 2"
Current solution:
vm.MainNews = db.News
.Select(n => new HomeMainNews {
Id = n.Id,
Date = n.DatePostedOn.ToString(),
Title = n.Title,
PictureURL = n.Pictures.Where(p => p.Type == 1).Select(p => p.Filename).FirstOrDefault().ToString()
}).ToList();
Automapper solution:
vm.MainNews = db.News.Project().To<HomeMainNews>().ToList();
Try this
Mapper.CreateMap<News, HomeMainNews>()
.ForMember(mainNew => mainNew.Date, opt => opt.MapFrom(news => news.DatePostedOn))
.ForMember(mainNew => mainNew.PictureURL, opt => opt.MapFrom(news => news.Pictures.First(pic => pic.Type == 2).Filename));

Resources