Apply cascade delete in one to many relationship - asp.net-mvc

If I have two required foreign keys in class and these keys compose this class primary key and we have another class contain list of this class how to implement cascade delete in this case entity framework code first
public class Post
{
public int Id { get; set; }
public string ClientName { get; set; }
public JobType JobType { get; set; }
public double JobBudget { get; set; }
public DateTime CreationDate { get; set; }
public string JobDescription { get; set; }
public bool IsAccepted { get; set; }
public string ClientId { get; set; }
public List<Proposal> Proposals { get; set; }
public ApplicationUser Client { get; set; }
}
public class Proposal
{
public string FreelancerId { get; set; }
public int PostId { get; set; }
public bool IsAccepted { get; set; }
public ApplicationUser Freelancer { get; set; }
public Post Post { get; set; }
}
public PostConfigurations()
{
Property(p => p.ClientName)
.IsRequired();
Property(p => p.JobType)
.IsRequired();
Property(p => p.JobBudget)
.IsRequired();
Property(p => p.CreationDate)
.IsRequired();
Property(p => p.JobDescription)
.IsRequired()
.HasMaxLength(255);
HasOptional(p => p.Proposals)
.WithOptionalDependent()
.WillCascadeOnDelete(true)
}
public class ProposalConfigurations : EntityTypeConfiguration<Proposal>
{
public ProposalConfigurations()
{
HasKey(p => new { p.FreelancerId, p.PostId });
Property(p => p.FreelancerId)
.IsRequired();
Property(p => p.PostId)
.IsRequired();
}
}
I tried many things, but failed, can you please help?

Related

EF6 migration - FK to entity with composite Key error

I have the following entities:
public class MeetingAttendee
{
public int MeetingId { get; set; }
public Meeting Meeting { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public IEnumerable<MeetingAttendanceEntry> MeetingAttendanceEntries { get; set; }
}
public class MeetingAttendanceEntry
{
public int Id { get; set; }
public int MeetingId { get; set; }
public Meeting Meeting { get; set; }
public int MeetingAttendeeId { get; set; }
public MeetingAttendee MeetingAttendee { get; set; }
public AttendanceStatus AttendanceStatus { get; set; }
}
The MeetingAttendee is set as:
modelBuilder.Entity<MeetingAttendee>().HasKey(pk => new { pk.MeetingId, pk.UserId });
modelBuilder.Entity<MeetingAttendee>().HasRequired(o => o.User).WithMany(m => m.MeetingAttendees).HasForeignKey(fk => fk.UserId);
modelBuilder.Entity<MeetingAttendee>().HasRequired(o => o.Meeting).WithMany(m => m.Attendees).HasForeignKey(fk => fk.MeetingId);
And when I'm trying to add MeetingAttendanceEntry, I'm getting "The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical" validation error.
I think is coming from the composite key, but everything I tried fails.
I tried from the parent entity:
modelBuilder.Entity<MeetingAttendee>().HasMany(m => m.MeetingAttendanceEntries).WithRequired(e => e.MeetingAttendee).HasForeignKey(e => e.MeetingAttendeeId);
From the child:
modelBuilder.Entity<MeetingAttendanceEntry>().HasRequired(e => e.MeetingAttendee).WithMany(m => m.MeetingAttendanceEntries).HasForeignKey(e => e.MeetingAttendeeId);
I tried adding the User and UserId to MeetingAttendanceEntry, and then setting it as FK as well:
modelBuilder.Entity<MeetingAttendanceEntry>().HasRequired(e => e.User).WithMany().HasForeignKey(e => e.UserId);
but still no luck.
What I'm missing?

Automapper not mapping my list properties

In my MVC5 project I use automapper to map my viewmodels to my models. But it seems that I'm doing something wrong, because not all my properties are mapped.
Here is my View Model
public class PlanboardViewModel
{
public int Id { get; set; }
[Display(Name = "Titel")]
public string Title { get; set; }
[Display(Name = "Omschrijving")]
public string Description { get; set; }
[Display(Name = "Verzoektype")]
public int AbsenceTypeId { get; set; }
public List<PlanboardEventMapViewModel> EventMap { get; set; }
public List<PlanboardEventDetail> EventDetails { get; set; }
public List<PlanboardRequest> PlanboardRequests { get; set; }
}
I use a separate class for my profiles:
public class PlanboardMappingProfile : Profile
{
protected override void Configure()
{
//CreateMap<AbsenceType, AbsenceTypeViewModel>();
//.ForAllMembers(opt => opt.Condition(s => !s.IsSourceValueNull));
CreateMap<PlanboardViewModel, Planboard>()
.ForMember(dest => dest.CSVHPlanboardEventDetail, opt => opt.MapFrom(src => src.EventDetails))
.ForMember(dest => dest.CSVHPlanboardEventMap, opt => opt.MapFrom(src => src.EventMap))
.ForMember(dest => dest.CSVHPlanboardRequest, opt => opt.MapFrom(src => src.PlanboardRequests));
CreateMap<PlanboardEventMapViewModel, PlanboardEventMap>();
}
}
In my repository I have the following code:
public int Create(PlanboardViewModel planboardViewModel)
{
try {
// map the viewmodel to the planboard model
// Map the planboards to the view model
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<PlanboardMappingProfile>();
cfg.CreateMap<PlanboardViewModel, Planboard>();
cfg.CreateMap<PlanboardEventMapViewModel, PlanboardEventMap>();
});
IMapper mapper = config.CreateMapper();
Planboard planboard = mapper.Map<Planboard>(planboardViewModel);
// Some more code here
When I submit the page and use the debugger, It shows that planboardViewModel has a list of values for PlanboardEventMapViewModel, PlanboardEventDetail, PlanboardRequest. The system is not telling me that there are any errors. When I check planboard after the mapping, it does not show any values for CSVHPlanboardEventDetail, CSVHPlanboardEventMap and CSVHPlanboardRequest.
EDIT
My PlanboardModel is created DB First EF6:
public partial class Planboard
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Planboard()
{
this.CSVHPlanboardEventDetail = new HashSet<PlanboardEventDetail>();
this.CSVHPlanboardEventMap = new HashSet<PlanboardEventMap>();
this.CSVHPlanboardRequest = new HashSet<PlanboardRequest>();
}
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int StatusID { get; set; }
public Nullable<int> AbsenceTypeID { get; set; }
public virtual AbsenceType AbsenceTypes { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PlanboardEventDetail> CSVHPlanboardEventDetail { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PlanboardEventMap> CSVHPlanboardEventMap { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PlanboardRequest> CSVHPlanboardRequest { get; set; }
}

NHibernte CreateAlias for 2 multiply class

I have 3 classes: Book, Genre, Authors
public class Book {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual int MfRaiting { get; set; }
public virtual int PageNumber { get; set; }
public virtual IList<Genre> Genres { get; set; }
public virtual Series Series { get; set; }
public virtual Mind Mind { get; set; }
public virtual IList<Author> Authors { get; set; }
public Book() {
Genres = new List<Genre>();
Authors = new List<Author>();
}
}
public class Genre {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Book> Books { get; set; }
public Genre() {
Books=new List<Book>();
}
}
public class Author {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string SurName { get; set; }
public virtual string Biography { get; set; }
public virtual IList<Book> Books { get; set; }
public Author() {
Books=new List<Book>();
}
}
And his classMaps
public class BookMap : ClassMap<Book> {
public BookMap() {
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Genres)
.Cascade.All()
.Table("Book_Genre");
HasManyToMany(x => x.Authors)
.Cascade.All()
.Table("Book_Author");
References(x => x.Series);
HasOne(x => x.Mind).Constrained();
}
}
public class GenreMap : ClassMap<Genre> {
public GenreMap() {
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Books)
.Cascade.All()
.Inverse()
.Table("Book_Genre");
}
}
public class AuthorMap : ClassMap<Author> {
public AuthorMap() {
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.SurName);
Map(x => x.Biography);
HasManyToMany(x => x.Books)
.Cascade.All()
.Inverse()
.Table("Book_Author");
}
}
When i try write in code
var criteria = session.CreateCriteria();
criteria.CreateAlias("Genres", "genre", JoinType.LeftOuterJoin);
it works well, but when i do so
public ActionResult Index()
{
var criteria = session.CreateCriteria<Book>();
criteria.CreateAlias("Genres", "genre", JoinType.LeftOuterJoin);
criteria.CreateAlias("Authors", "author", JoinType.LeftOuterJoin);
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
}
i see exception Cannot simultaneously fetch multiple bags. How can I get result of that criteria?
Thank
I resolve this problem! I replace IList on ISet, and replace new List<"Class"> on new HashSet<"Class">
I read this problem here.
http://developer-should-know.tumblr.com/post/118012584847/jpa-fetching-strategies Only one collection that is fetched using JOIN strategy can be of type List, other collection must be of type Set. Otherwise an exception will be thrown:
HibernateException: cannot simultaneously fetch multiple bags

Entity Framework Fluent API

My Entities are as follows...
public class Project{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
}
public class Survey{
public int Id { get; set; }
public int ProjectId { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
}
public class Category{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
}
public class SurveyCategory{
public int Id { get; set; }
public int SurveyId{ get; set; }
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual Survey Survey { get; set; }
public virtual Category Category { get; set; }
}
A project will have list of Surveys, A Survey will have only one Category, A Category can have multiple Survey, SurveyCategory is the table where I am storing Survey + Category link.
Can anyone direct me to what would be appropriate Fluent API code will be for this to map properly.... So far I have this....
protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Project>().HasMany(project => project.Surveys);}
hi I hope I understood what you are looking for.
First of al you should do a few changes to your model
public class Project
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
}
public class Survey
{
public int Id { get; set; }
public int ProjectId { get; set; }
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<SurveyCategory> SurveyCategory { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
public virtual ICollection<SurveyCategory> SurveyCategory { get; set; }
}
public class SurveyCategory
{
public int Id { get; set; }
public string Name { get; set; }
public int SurveyId { get; set; }
public virtual Survey Survey { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
And then on the model creating you should do this
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>()
.HasMany(p => p.Surveys)
.WithRequired(u => u.Project);
modelBuilder.Entity<Category>()
.HasMany(p => p.Surveys)
.WithRequired(u => u.Category);
modelBuilder.Entity<Category>()
.HasMany(p => p.SurveyCategory)
.WithRequired(u => u.Category)
.HasForeignKey(k => k.CategoryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Survey>()
.HasMany(p => p.SurveyCategory)
.WithRequired(u => u.Survey)
.HasForeignKey(k => k.SurveyId)
.WillCascadeOnDelete(false);
}
I hope this helps

NCommon 1.1 and EF4

I am new to NCommon and am looking for an example project to get started.
I am using EF4.
I assume one needs to use EF4 with POCOs?
Thanks for any help.
NCommon.Configure.Using(new StructureMapContainerAdapter(ObjectFactory.Container))
.ConfigureState<DefaultStateConfiguration>()
.ConfigureData<EFConfiguration>(config => config.WithObjectContext(
() =>
{
SiteContext db = new SiteContext(ConfigurationManager.ConnectionStrings["TestTheBest"].ConnectionString);
if (Transaction.Current != null )
{
db.Context.Connection.Open();
}
return db.Context;
}))
.ConfigureUnitOfWork<DefaultUnitOfWorkConfiguration>(config => config.AutoCompleteScope());
public class SiteContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Test> Tests { get; set; }
public DbSet<Client> Clients { get; set; }
public DbSet<Question> Questions { get; set; }
public DbSet<Section> Sections { get; set; }
public DbSet<Answer> Answers { get; set; }
public DbSet<GlobalSettings> GlobalSettings { get; set; }
public DbSet<PassageTest> PassageTest { get; set; }
public DbSet<PassageTestAnswer> PassageTestAnswer { get; set; }
public DbSet<SaaSUser> SaaSUser { get; set; }
public SiteContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
Context.SavingChanges += new EventHandler(Context_SavingChanges);
}
void Context_SavingChanges(object sender, EventArgs e)
{
if(Context.Connection.State==ConnectionState.Open)
Context.Connection.Close();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(x => x.Invitations).WithRequired(x=>x.user).WillCascadeOnDelete(true);
modelBuilder.Entity<User>().HasMany(x => x.PassageTests).WithRequired(x => x.user).WillCascadeOnDelete(true);
modelBuilder.Entity<PassageTest>().HasMany(x => x.PassageTestAnswers).WithRequired(x => x.passageTest).WillCascadeOnDelete(true);
// modelBuilder.Entity<Company>().HasMany(x => x.Users).WithRequired(x => x.company).WillCascadeOnDelete(true);
modelBuilder.Entity<Question>().HasMany(x => x.Answers).WithRequired(x => x.question).WillCascadeOnDelete(true);
modelBuilder.Entity<Question>().HasMany(x => x.PassageTestAnswers).WithRequired(x => x.question).WillCascadeOnDelete(true);
modelBuilder.Entity<Test>().HasMany(x => x.Invitations).WithRequired(x => x.test).WillCascadeOnDelete(true);
modelBuilder.Entity<Test>().HasMany(x => x.PassageTests).WithRequired(x => x.test).WillCascadeOnDelete(true);
modelBuilder.Entity<Test>().HasMany(x => x.Sections).WithRequired(x => x.test).WillCascadeOnDelete(true);
modelBuilder.Entity<Client>().HasMany(x => x.Tests).WithRequired(x => x.client).WillCascadeOnDelete(true);
}
public ObjectContext Context
{
get { return ((IObjectContextAdapter)this).ObjectContext; }
}
}

Resources