Entity Framework 1 to 1 / 1 to * - entity-framework

I have this setup of classes:
public class User
{
public int Id { get; set; }
public string LoginName { get; set; }
public int CurrentPasswordId { get; set; }
public virtual ArchivedPassword CurrentPassword {get;set;}
public virtual ICollection<ArchivedPassword> UsedPasswords { get; set; }
}
public class ArchivedPassword
{
public int Id { get; set; }
public string Hash { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<User> Users { get; set; }
}
ModelBuilder.Entity<ArchivedPassword>()
.HasMany(e => e.Users)
.WithRequired(e => e.CurrentPassword)
.HasForeignKey(e => e.CurrentPasswordId)
.WillCascadeOnDelete(false);
ModelBuilder.Entity<User>()
.HasMany(e => e.UsedPasswords)
.WithRequired(e => e.User)
.HasForeignKey(e => e.UserId)
.WillCascadeOnDelete(false);
When i try to add a user and a password, ef canĀ“t figure out the update order.
Is this a mapping Problem?

I am not expert on Database .But i think you can not make two different Foreign Keys for same tables.But you can success what you want as below code
public class UserContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Password> Paswords { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public Password Password
{
get
{
return Passwords.ElementAt(Passwords.Count - 1);
}
}
public virtual ICollection<Password> Passwords { get; set; }
}
public class Password
{
public int Id { get; set; }
public string Hash { get; set; }
public virtual User User { get; set; }
}

Related

Entity Framework Core - 3 tier relationship

I have to apply a set of relationships with a system that incorporates a messaging system.
I have the two of my domain object with one mapping object (for the many-to-many relationship):
public class User
{
public User()
{
UserMails = new List<UserMail>();
}
public int Id { get; set; }
public ICollection<UserMail> UserMails { get; set; }
}
public class Mail
{
public Mail()
{
UserMails = new List<UserMail>();
}
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public ICollection<UserMail> UserMails { get; set; }
}
public class UserMail
{
public int Id { get; set; }
public int FromUserId { get; set; }
public User FromUser { get; set; }
public int ToUserId { get; set; }
public User ToUser { get; set; }
public int MailId { get; set; }
public Mail Mail { get; set; }
}
How would I configure this relationship using Fluent API such that there's a many to many relationship between User and Mail and Mail can have 2 foreign keys back to the UserFrom and UserTo?
Any help on this would be greatly appreciated.
If you are trying to model the relationship between a mail and its sender/recipient, then you don't need a many-to-many relation, or 2 foreign keys in your joining entity. Instead, you need 2 one-to-many relations like below -
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Mail> ReceivedMails { get; set; }
public ICollection<Mail> SentMails { get; set; }
}
public class Mail
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public int SenderId { get; set; }
public User Sender { get; set; }
public int RecipientId { get; set; }
public User Recipient { get; set; }
}
and you can configure them as -
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Mail>()
.HasOne(p => p.Sender)
.WithMany(p => p.SentMails)
.HasForeignKey(p => p.SenderId)
.OnDelete(DeleteBehavior.NoAction);
builder.Entity<Mail>()
.HasOne(p => p.Recipient)
.WithMany(p => p.ReceivedMails)
.HasForeignKey(p => p.RecipientId)
.OnDelete(DeleteBehavior.NoAction);
}

Defining the one to many relationship in OnModelCreating using Entity Framework Core 3.1

I am new to Entity Framework Core 3.1 and trying to define the one-to-many relationship between two tables. I am currently struggling and getting compilation errors. Could somebody tell me what the problem could be.
The error is:
PersonNote does not contain the definition for PersonNote
I am currently getting is at line
entity.HasOne(d => d.PersonNote)
How else could I define one-to-many relationship?
The two tables are Person and PersonNote. One Person can have many PersonNotes. I have defined the models for them
public class Person
{
public int Id { get; set; }
public int? TitleId { get; set; }
public string FirstName { get; set; }
public string FirstNamePref { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Gender { get; set; }
public int AddressId { get; set; }
public string TelephoneNumber { get; set; }
public string MobileNumber { get; set; }
public string Email { get; set; }
public int? PartnerId { get; set; }
public bool Enabled { get; set; }
public string CreatedBy { get; set; }
public DateTime Created { get; set; }
public string ModifiedBy { get; set; }
public DateTime Modified { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordStartDateTime { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordEndDateTime { get; set; }
public Address Address { get; set; }
public Title Title { get; set; }
public Client Client { get; set; }
internal static IEnumerable<object> Include(Func<object, object> p)
{
throw new NotImplementedException();
}
public PersonNote PersonNote { get; set; }
}
public class PersonNote
{
public int Id { get; set; }
public int PersonId { get; set; }
public string Note { get; set; }
public int AuthorId { get; set; }
public string CreatedBy { get; set; }
public DateTime Created { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordStartDateTime { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordEndDateTime { get; set; }
}
public IEnumerable<PersonNote> GetPersonNotes(int personId)
{
var PersonNotes = PersonNote
.Include(x => x.)
.Where(x => x.Id == personId)
.ToList();
return PersonNotes;
}
I have tried the following in OnModelCreating:
modelBuilder.Entity<PersonNote>(entity =>
{
entity.ToTable("PersonNote", "common");
entity.HasOne(d => d.PersonNote)
.WithMany(p => p.Person)
.HasForeignKey(d => d.PersonId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_commonPersonNote_commonPerson");
});
You should have have something like this (other properties are omitted):
class Person
{
[Key]
public int Id { get; set; }
public List<PersonNote> PersonNotes { get; set; }
}
class PersonNote
{
[Key]
public int Id { get; set; }
public int PersonId { get; set; }
}
class StackOverflow : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<PersonNote> PersonNotes { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.HasMany(p => p.PersonNotes)
.WithOne()
.HasForeignKey(p => p.PersonId);
}
}

Entity Framework. Resolve Zero Or One to one use one navigation property

Sorry for my English. I have the following entity:
public class MediaAlbum
{
[Key]
public Guid AlbumId { get; set; }
public string Title { get; set; }
public virtual ICollection<MediaImage> Images { get; set; }
public Guid? CoverId { get; set; }
[ForeignKey("ImageId")]
public virtual MediaImage Cover { get; set; }
}
public class MediaImage
{
[Key]
public Guid ImageId { get; set; }
public string Image { get; set; }
public Guid AlbumId { get; set; }
[ForeignKey("AlbumId")]
public virtual MediaAlbum Album { get; set; }
}
I need map navigation property Cover to Entity 'MediaImage'.
I tried to solve through fluentApi, but it not worked:
modelBuilder.Entity<MediaAlbum>().HasOptional(x => x.Cover).WithOptionalPrincipal()
.Map(x => x.MapKey("ImageId"));
use this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MediaAlbum>().HasMany(x => x.Images)
.WithRequired(x => x.Album).HasForeignKey(x=>x.AlbumId);
modelBuilder.Entity<MediaAlbum>().HasOptional(x => x.Cover);
}
foreign key is CoverId not ImageId:
public class MediaAlbum
{
[Key]
public Guid AlbumId { get; set; }
public string Title { get; set; }
public virtual ICollection<MediaImage> Images { get; set; }
public Guid? CoverId { get; set; }
[ForeignKey("CoverId")]// change to this
public virtual MediaImage Cover { get; set; }
}
Try this:
modelBuilder.Entity<MediaAlbum>()
.HasOptional(x => x.Cover)
.WithRequired(x => x.Album)
.WillCascadeOnDelete();

Entity Framework Code First Fluent API One to Many

I have a ProductRequests table. It has a one to one relationship to ProductRequestDepartments. Which works correctly. I want to link ProductRequestDetails (which will have the actual Products (1 or more) of the ProductRequests.
public partial class WP__ProductRequests
{
[Key]
public int RequestId { get; set; }
[Required]
[StringLength(30)]
public string FromLocation { get; set; }
[Required]
public int ToDepartmentId { get; set; }
[StringLength(4000)]
public string Reason { get; set; }
[Required]
[StringLength(50)]
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
[StringLength(50)]
public string CompletedBy { get; set; }
public DateTime? CompletedDate { get; set; }
[Required]
[StringLength(1)]
public string Status { get; set; }
public ICollection<WP__ProductRequestDetails> ProductRequestDetails { get; set; }
public ICollection<WP__ProductRequestDepartments> ProductRequestDepartments { get; set; }
}
public partial class WP__ProductRequestDetails
{
[Key]
public int RequestDetailsId { get; set; }
[Required]
public int RequestId { get; set; }
[StringLength(20)]
public string ItemCode { get; set; }
[StringLength(100)]
public string ItemName { get; set; }
public int? Quantity { get; set; }
[Required]
[StringLength(1)]
public string Approved { get; set; }
public WP__ProductRequests ProductRequest { get; set; }
}
public partial class WP_ProductRequestDepartments
{
[Key]
public int ID { get; set; }
[StringLength(100)]
public string Department { get; set; }
public int? ApprovalManager { get; set; }
[StringLength(60)]
public string Reason { get; set; }
[StringLength(25)]
public string GeneralLedger { get; set; }
}
How do I wire this up in the Fluent API. So far I tried
public virtual DbSet<WP__ProductRequestDepartments> WP__ProductRequestDepartments { get; set; }
public virtual DbSet<WP__ProductRequestDetails> WP__ProductRequestDetails { get; set; }
public virtual DbSet<WP__ProductRequests> WP__ProductRequests { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<WP__ProductRequestDetails>()
.Property(e => e.Approved)
.IsFixedLength()
.IsUnicode(false);
modelBuilder.Entity<WP__ProductRequests>()
.Property(e => e.Status)
.IsFixedLength()
.IsUnicode(false);
modelBuilder.Entity<WP__ProductRequests>()
.HasRequired(a => a.ProductRequestDepartments)
.WithMany()
.HasForeignKey(a => a.ToDepartmentId);
//??
modelBuilder.Entity<WP__ProductRequests>()
.HasRequired(a => a.ProductRequestDetails)
.WithMany()
.HasForeignKey(a => a.RequestId);
}
ProductRequests -> ProductRequestDepartments works correctly (1 : 1)
ProductRequests -> ProductRequestDetail does NOT work (1 : N)
I'm getting
One or more validation errors were detected during model generation:"
WP__ProductRequests_ProductRequestDetails_Source: : Multiplicity is not valid in Role 'WP__ProductRequests_ProductRequestDetails_Source' in relationship 'WP__ProductRequests_ProductRequestDetails'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be '1'.
I believe you are looking for
modelBuilder.Entity<WP__ProductRequestDetails>()
.HasRequired(productRequestDetails => productRequestDetails.ProductRequest)
.WithMany(productRequest => productRequest.ProductRequestDetails)
.HasForeignKey(productRequestDetails => productRequestDetails.RequestId);

EF Adding an additional FK?

I have the following 2 entities:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Fixture> Fixtures { get; set; }
}
public class Fixture
{
public int Id { get; set; }
public Result Result { get; set; }
public int HomeTeamId { get; set; }
public int AwayTeamId { get; set; }
public virtual Team HomeTeam { get; set; }
public virtual Team AwayTeam { get; set; }
}
I have then mapped it like so:
public class FixtureMap : EntityTypeConfiguration<Fixture>
{
public FixtureMap()
{
HasRequired(x => x.AwayTeam).WithMany().HasForeignKey(x => x.AwayTeamId);
HasRequired(x => x.HomeTeam).WithMany().HasForeignKey(x => x.HomeTeamId);
}
}
But when I add a migration, EF is creating an additional FK and column to my Fixture table and I've no idea why? How can I tell it not too?
As you can see its added a column called Team_Id and created an FK from it even tho I have specified the relationship in the mapping?
use this code:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("HomeTeam")]
public virtual ICollection<Fixture> HomeFixtures { get; set; }
[InverseProperty("AwayTeam")]
public virtual ICollection<Fixture> AwayFixtures { get; set; }
}
public class Fixture
{
public int Id { get; set; }
public Result Result { get; set; }
public int HomeTeamId { get; set; }
public int AwayTeamId { get; set; }
[InverseProperty("HomeFixtures")]
[ForeignKey("HomeTeamId ")]
public virtual Team HomeTeam { get; set; }
[InverseProperty("AwayFixtures")]
[ForeignKey("AwayTeamId")]
public virtual Team AwayTeam { get; set; }
}
And :
public class FixtureMap : EntityTypeConfiguration<Fixture>
{
public FixtureMap()
{
HasRequired(x => x.AwayTeam).WithMany().HasForeignKey(x => x.AwayTeamId).willCascadeOnDelete(false);
HasRequired(x => x.HomeTeam).WithMany().HasForeignKey(x => x.HomeTeamId);
}
}