I have an Account object that contains an "Id" field, which is mapped to a View in the database:
public class Account : GeneralInfo
{
[Column("first_name")]
public string FirstName { get; set; }
[Column("last_name")]
public string LastName { get; set; }
public string Designation { get; set; }
[Column("full_name")]
public string FullName { get; set; }
public string Email { get; set; }
[Column("member_type")]
public string MemberType { get; set; }
[Column("status")]
public string Status { get; set; }
[Column("paid_thru")]
public DateTime? PaidThru { get; set; }
[Column("member_record")]
public bool MemberRecord { get; set; }
[Column("category")]
public string Category { get; set; }
public virtual Subscription Subscriptions { get; set; }
}
I also have a Subscription object that uses the same "Id" as the account object:
[Table("Subscriptions")]
public class Subscription
{
[Column("Id")]
public string ID { get; set; }
[Column("Balance")]
public decimal Balance { get; set; }
}
When I try to use "subscription" as a navigation property of account, I get an error saying: {"Invalid column name 'Subscriptions_ID'."}
How can I access "subscriptions" using the Account object?
Use the fluent API to map the Shared PK relationaship.
public class MyContext : DbContext
{
// ...........
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Subscription>().HasRequired()
.WithOptional(a => a.Subscriptions);
}
}
Related
I am trying to set up audit properties for each of my Entities with an abstract Base class
public abstract class Base
{
public bool IsActive { get; set; }
public bool IsDeleted { get; set; }
public int CreatedByUserId { get; set; }
[ForeignKey("CreatedByUserId")]
public virtual User CreatedBy { get; set; }
public int ModifiedByUserId { get; set; }
[ForeignKey("ModifiedByUserId")]
public virtual User ModifiedBy { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
}
Somehow the Data Annotations doesn't work in EF Core but was working in my EF 6 Project
I am now receiving this error:
Unable to determine the relationship represented by navigation 'Address.CreatedBy' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
These are my models:
public class Address : Base
{
public int Id { get; set; }
public string StringAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class User : Base
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public string Email { get; set; }
public string ContactNumber { get; set; }
public string SecondaryContactNumber { get; set; }
public int RoleId { get; set; }
public Role Role { get; set; }
public HashSet<Address> Addresses { get; set; }
}
What's weird is when I remove the Base inheritance from my other entities apart from User, EF Core is able to set the FK without any errors.
How do I configure it manually with Fluent API?
I already have a BaseConfig class as starting point to be inherited by my other entity config classes:
public class BaseConfig<TEntity> : IEntityTypeConfiguration<TEntity> where TEntity : Base
{
public virtual void Configure(EntityTypeBuilder<TEntity> builder)
{
builder.Property(x => x.DateCreated).HasDefaultValueSql("GETDATE()");
builder.Property(x => x.DateModified).HasDefaultValueSql("GETDATE()");
// Am I setting this correctly?
builder
.HasOne(b => b.CreatedBy)
.WithMany()
.HasForeignKey(p => p.CreatedByUserId);
}
}
I am unable to save data using code first technique.
here is my context:
public virtual DbSet<Users> User { get; set; }
public virtual DbSet<Agency> Agencies { get; set; }
public virtual DbSet<ColdStorage> ColdStorages { get; set; }
public virtual DbSet<ShowRoom> ShowRooms { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
and my user model is here:
[Table("Users")]
public class Users
{
[Key]
public int UserId { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public bool isAgency { get; set; }
public bool isColdStorage { get; set; }
public string VerificationCode { get; set; }
public DateTime CreatedDate { get; set; }
// Reverse navigation
public virtual Agency Agency { get; set; }
public virtual ColdStorage ColdStorage { get; set; }
public virtual ShowRoom ShowRoom { get; set; }
public Users()
{
Agency = new Agency();
ColdStorage = new ColdStorage();
ShowRoom = new ShowRoom();
}
}
and my other model is here:
[Table("Agency")]
public class Agency
{
[Key]
public int AgencyId { get; set; }
[ForeignKey("Users")]
public int UserId { get; set; }
public string AgencyName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Description { get; set; }
public DateTime CreatedDate { get; set; }
[Required]
public virtual Users Users { get; set; }//Foriegn key
}
And the error is here:
Message":"An error has occurred.","ExceptionMessage":"One or more validation errors were detected during model generation:\r\n\r\nColdStorage_Users_Source: : Multiplicity is not valid in Role 'ColdStorage_Users_Source' in relationship 'ColdStorage_Users'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.\r\nShowRoom_Users_Source:
Just like the error says.
"because the Dependent Role properties are not the key properties, the
upper bound of the multiplicity of the Dependent Role must be '*'"
The "Dependent Role properties" here means, eg Agency.UserId, and the "multiplicity must be '*'" means Users must have a collection of Agencies. EG
public virtual ICollection<Agency> Agencies { get; } = new HashSet<Agency>();
Hello I have the classes:
Class User
public class User
{
public Int64 Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public Profile Profile { get; set; } //EF one to one
}
Class Profile
public class Profile
{
public Int64 Id { get; set; }
public string Skype { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual User User { get; set; } //This is because EF Mappings
}
Class User DTO
public class UserDTO
{
public string Name { get; set; }
public string Email { get; set; }
public Profile Profile { get; set; }
}
I did the configurations to Map User to UserDTO
Mapper.CreateMap<User, UserDTO>();
I need to have the Profile.User because of the Entity Framework One to One Relationship but I don't want the Profile.User to be shown in the Mapping.
How can I ignore the Profile.User?
You could use a UserProfileDTO class that omits User
public class UserProfileDTO
{
public string Skype { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public ICollection<AddressDTO> Addresses { get; set; }
}
public class UserDTO
{
public string Name { get; set; }
public string Email { get; set; }
public UserProfileDTO Profile { get; set; }
}
Mapper.CreateMap<User, UserDTO>();
Mapper.CreateMap<Profile, UserProfileDTO>();
Here's the problem. I have table User which have quite a few fields. What I want to do is split this table into multiple entities like this:
User
-> GeneralDetails
-> CommunicationDetails
-> Address
etc.
All goes well when extracting some fields from User into GeneralDetails. However, when I try to do the same thing for CommunicationDetails EF blows up and require to establish one-to-one relationship between GeneralDetails and CommunicationDetails.
Sample entities definition:
public class User {
public int UserId { get; set; }
public string SomeField1 { get; set; }
public int SomeField2 { get; set; }
public virtual GeneralDetails GeneralDetails { get; set; }
public virtual CommunicationDetails CommunicationDetails { get; set; }
public virtual Address Address { get; set; }
}
public class GeneralDetails {
[Key]
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public virtual User User { get;set; }
}
public class CommunicationDetails {
[Key]
public int UserId { get; set; }
public string Phone { get; set; }
public string DeviceToken { get; set; }
public virtual User User { get;set; }
}
public class Address {
[Key]
public int UserId { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Street { get; set; }
public virtual User User { get;set; }
}
Sample mapping:
modelBuilder.Entity<User>().
HasRequired(user => user.GeneralDetails).
WithRequiredPrincipal(details => details.User);
modelBuilder.Entity<User>().
HasRequired(user => user.CommunicationDetails).
WithRequiredPrincipal(details => details.User);
modelBuilder.Entity<User>().
HasRequired(user => user.Address).
WithRequiredPrincipal(details => details.User);
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<GeneralDetails>().ToTable("Users");
modelBuilder.Entity<Address>().ToTable("Users");
Why on earth EF want this relationship? Is there any way this could be solved?
The correct way to actually do this is by Complex Types rather than entities. Its actually a more common problem than you think.
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelbuilder.ComplexType<CommunicationDetails>();
modelbuilder.ComplexType<GeneralDetails>();
modelbuilder.ComplexType<Address>();
modelbuilder.Entity<User>().ToTable("Users");
}
}
Ok, I have been pulling out my hair because I simply cannot make a many to many relationship. I have the following two models:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string CompanyName { get; set; }
public string FirstName { get; set; }
public string Lastname { get; set; }
public string EmailAddress { get; set; }
public string PhoneNumber { get; set; }
public bool? ChangePassword { get; set; }
public bool? Deletable { get; set; }
//Add more Properties for more fields
public virtual IQueryable<CompanyInformation> ParentCompany { get; set; }
}
and
public class CompanyInformation
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[DisplayName("Company Name:")]
public string companyName { get; set; }
[DisplayName("Website Address:")]
[Url(ErrorMessage="The Website field is not a valid fully-qualified http, https, or ftp URL. (Example: http://www.website.com)")]
public string website { get; set; }
public string contactTitle { get; set; }
[DisplayName("Contact First Name:")]
public string contactFirstName { get; set; }
//[Required]
[DisplayName("Contact Last Name:")]
public string contactLastName { get; set; }
[Phone]
[DisplayName("Phone Number:")]
public string contactPhoneNumber { get; set; }
[DisplayName("Address Display?")]
public bool displayAddress { get; set; }
[DisplayName("Phone Number?")]
public bool displayPhoneNumber { get; set; }
[DisplayName("Address 1:")]
public string address1 { get; set; }
[DisplayName("Address 2:")]
public string address2 { get; set; }
[DisplayName("City:")]
public string city { get; set; }
[DisplayName("State:")]
public string state { get; set; }
[DisplayName("Zip/Postal Code:")]
public string zipCode { get; set; }
[DisplayName("Search Engine?")]
public bool allowSearchEngines { get; set; }
//Navigation Property
public virtual IQueryable<UserProfile> CompanyUsers{ get; set; }
}
I'm trying to make a many-to-many relationship between these two and I just can't figure out how to do it properly. I should mention that I am very new to the EF Code First.
My Context Class looks like the following:
public class myDB : DbContext
{
public SchedulerDB()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<CompanyInformation> Companies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<UserProfile>().HasMany(e => e.ParentCompanies).WithMany(e => e.CompanyUsers);
}
}
ok, As soon as I add the modelBuilder above I get the following error:
The type arguments for method 'System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Scheduler.Model.UserProfile>.HasMany<TTargetEntity>(System.Linq.Expressions.Expression<System.Func<Scheduler.Model.UserProfile,System.Collections.Generic.ICollection<TTargetEntity>>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. C:\Users\Hiva\Documents\Project\ToDo\Infrastructure\myDB.cs
What am I doing wrong? I can't seem to find any examples that use the modelBuilder differently to achieve a many-to-many relationship between two tables. Thank you in advanced for your help.
You should use ICollection for navigation properties:
ICollection<UserProfile> CompanyUsers{ get; set; }
and
ICollection<UserProfile> ParentCompanies{ get; set; }
instead of IQueriable