I would like to create Resource and RelatedResources table with EF Code First as below:
Table Resource
int Id
string ResourceName
int Category
Table RelatedResource
int ResourceId
int RelatedResourceId
I tried as below but
Error: The ForeignKeyAttribute on property 'ResourceId' on type 'Models.ResourceRelated' is not valid. The navigation property 'Resource' was not found on the dependent type 'Models.ResourceRelated'. The Name value should be a valid navigation property name.
public class ResourceRelated
{
[ForeignKey("Resource")]
public int ResourceId { get; set; }
public virtual Resource Resoure { get; set; }
public virtual ICollection<Resource> RelatedResource { get; set; }
}
Kindly Advice!
If you want RelatedResource table, than you want many-to-many relationship. You can achieve this in next way
public class Resource
{
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public int Category { get; set; }
[InverseProperty("Resoure")]
public virtual ICollection<RelatedResource> RelatedResource { get; set; }
[InverseProperty("ResourceRelated")]
public virtual ICollection<RelatedResource> ResourceRelated { get; set; }
}
public class RelatedResource
{
[Key]
[Column(Order = 1)]
[ForeignKey("Resoure")]
public int ResourceId { get; set; }
[Key]
[Column(Order = 2)]
[ForeignKey("ResourceRelated")]
public int ResourceRelatedId { get; set; }
public virtual Resource Resoure { get; set; }
public virtual Resource ResourceRelated { get; set; }
}
If you prefer do not work with RelatedResource in code, than you can do next
public class Resource
{
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public int Category { get; set; }
public virtual ICollection<Resource> RelatedResource { get; set; }
public virtual ICollection<Resource> ResourceRelated { get; set; }
}
After you need next additional configuration
internal class ResourceConfiguration : EntityTypeConfiguration<Resource>
{
public ResourceConfiguration()
{
HasMany(s => s.ResourceRelated).WithMany(c => c.RelatedResource)
.Map(cs => {
cs.MapLeftKey("ResourceId");
cs.MapRightKey("RelatedResourceId");
cs.ToTable("RelatedResource"); }
);
}
}
And finally add this configuration
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
///other configuration code
modelBuilder.Configurations.Add(new ResourceConfiguration());
}
But if you want to have "resource tree" than you do not need RelatedResource table
public class Resource
{
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public int Category { get; set; }
public int? ResourceRelatedId { get; set; }
public Resource ResourceRelated { get; set; }
[ForeignKey("ResourceRelatedId")]
public virtual ICollection<Resource> RelatedResource { get; set; }
}
Related
I get an error when I use EF Core 7 to create entities.
The entity type 'List' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
I have found the error prop, that's Project of service entity, when I only annotate Project of service entity, then I can run Add-Migration successfully. I don't know why and I also don't know how to fix this error.
Does somebody know this error? Please help...
public class Service : EntityBase
{
public Guid? DefaultCapacityUnitId { get; set; }
public Guid? DefaultSizeUnitId { get; set; }
public virtual SizeUnit DefaultSizeUnit { get; set; }
public Guid ProjectId { get; set; }
public Project Project { get; set; }
public Guid? ParentId { get; set; }
public virtual Service Parent { get; set; }
public Guid DisciplineId { get; set; }
public virtual Discipline Discipline { get; set; }
public virtual List<Service> SubServices { get; set; } = new List<Service>();
}
public class Equipment : EntityBase
{
public Guid ProjectId { get; set; }
public Project Project { get; set; }
public Guid? ServiceId { get; set; }
public virtual Service Service { get; set; }
public Guid DisciplineId { get; set; }
public virtual Discipline Discipline { get; set; }
}
public abstract class EntityBase
{
[Key]
public virtual Guid Id { get; set; } = Guid.NewGuid();
private string name;
[Required, MaxLength(200)]
public virtual string Name
{
get
{
return name?.Trim();
}
set
{
name = value?.Trim();
}
}
private string shortName;
[Required, MaxLength(100)]
public virtual string ShortName
{
get
{
return shortName?.Trim();
}
set
{
shortName = value?.Trim();
}
}
[NotMapped]
public EntityBase Snapshot { get; set; }
[NotMapped]
public List<string> ValueChangedProperties { get; set; } = new List<string>();
}
public class Project : EntityBase
{
}
public class Discipline : EntityBase
{
public Guid ProjectId { get; set; }
public virtual Project Project { get; set; }
public virtual List<Service> Services { get; set; } = new List<Service>();
public Guid? ScenarioId { get; set; }
public Guid? ParentId { get; set; }
public virtual Discipline Parent { get; set; }
}
public partial class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions<TestDbContext> options)
: base(options)
{ }
public TestDbContext()
{
}
public DbSet<Project> Projects { get; set; }
public DbSet<Discipline> Disciplines { get; set; }
public DbSet<Service> Services { get; set; }
public DbSet<ServiceGroup> ServiceGroups { get; set; }
public DbSet<SizeUnit> SizeUnits { get; set; }
public DbSet<Equipment> Equipments { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entityTypes = typeof(TestDbContext).GetProperties()
.Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
.Select(p => p.PropertyType.GetGenericArguments()[0]).ToList();
entityTypes.ForEach(entityType => {
var entityName = entityType.Name;
modelBuilder.Entity(entityType).ToTable(entityName);
});
modelBuilder.Entity<ServiceMapping>().HasOne(x => x.Service).WithMany().HasForeignKey(x => x.ServiceId).OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<ServiceMapping>().HasOne(x => x.TargetService).WithMany().HasForeignKey(x => x.TargetServiceId).OnDelete(DeleteBehavior.Cascade);
base.OnModelCreating(modelBuilder);
}
}
public class ServiceGroup : EntityBase
{
public Guid ProjectId { get; set; }
public virtual Project Project { get; set; }
public Guid? ScenarioId { get; set; }
}
public class ServiceMapping : EntityBase
{
public Guid ProjectId { get; set; }
public virtual Project Project { get; set; }
public Guid ServiceId { get; set; }
public virtual Service Service { get; set; }
public Guid TargetServiceId { get; set; }
public virtual Service TargetService { get; set; }
}
public class SizeUnit : EntityBase
{
public Guid ProjectId { get; set; }
public virtual Project Project { get; set; }
public int UnitType { get; set; }
}
If I annotate Project of service entity, then it's all right.
My EF Code First model for some reason is not in sync with the db. I'm getting this error:
{"Invalid column name 'Type_Id1'."}
The field is actually called 'Type_Id' so I'm not sure from where that 1 comes up. I have the table column called as Type_Id and also I've added a Type_Id in my type entity model.
Why might I be getting that error message, plus why I'm getting 1 at the end of the name?
Update
My Task class:
public class Task
{
public Task()
{
Language = 1;
Grades = new HashSet<Grade>();
Categories = new HashSet<Category>();
Subjects = new HashSet<Subject>();
Rooms = new Collection<Room>();
Tools = new Collection<Tool>();
}
[Key]
public int Id { get; set; }
public string Description { get; set; }
public virtual TaskType Type { get; set; }
public string Rules { get; set; }
[Required]
[StringLength(200), MinLength(1)]
public string Name { get; set; }
public int PreperationTime { get; set; }
public int InstructionTime { get; set; }
public int TaskTime { get; set; }
public int Type_Id { get; set; }
public string VideoLink { get; set; }
[Required]
public int Language { get; set; }
public int? MinimumParticipants { get; set; }
public int? MaximumParticipants { get; set; }
public int? Rating { get; set; }
[Required]
public string CreatedBy { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
public virtual ICollection<Tool> Tools { get; set; }
}
DBContext class:
public ApplicationDbContext() : base("DefaultConnection", false)
{
}
public DbSet<Task> Tasks { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
You need to add the FK attribute on your navigation property. EF is creating Type_Id1 because Type_Id already exists (although it can't tell by convention it is the FK).
[ForeignKey("Type_Id")]
public virtual TaskType Type { get; set; }
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships
I'm getting this error when trying to update relationship (one to one)
with fluent api this are my classes :
public class Organisation
{
[Key]
public int OrganisationId { get; set; }
public string organisationName { get; set; }
public string FirstName { get; internal set; }
public string LastName { get; internal set; }
public virtual ApplicationUser User { get; set; }
[Required]
public string ApplicationUserId { get; set; }
public int? OrganisationDetalisId { get; set; }
public virtual OrganisationDetalis OrDetalis { get; set; }
public virtual ICollection<Aeroa> aeroa { get; set; }
public virtual ICollection<Order> orders { get; set; }
}
public class OrganisationDetalis
{
[Key]
public int OrganisationDetalisId { get; set; }
//remove for clear code
public int OrganisationId { get; set; }
public virtual Organisation organisation { get; set; }
}
public DbSet<Organisation> organisation { get; set; }
public DbSet<OrganisationDetalis> OrDetalis { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<OrganisationDetalis>()
.HasKey(o => o.OrganisationId);
modelBuilder.Entity<Organisation>()
.HasOptional(ad => ad.OrDetalis).WithRequired(oo => oo.organisation);
}
but I keep getting that error when updating view nugget console
where is the problem?
I have following tables and need to set relationship between them.
Model classes for the tables are as given
public class UserAction
{
public int ActionID { get; set; }
public string ActionName { get; set; }
public virtual ICollection<RoleScreenActionPermission> RoleScreenActionPermissions { get; set; }
}
public class Screen
{
public int ScreenID { get; set; }
public string ScreenName { get; set; }
public virtual ICollection<RoleScreenActionPermission> RoleScreenActionPermissions { get; set; }
}
public class ScreenAction
{
public int ScreenActionID { get; set; }
public int ScreenID { get; set; }
public int ActionID { get; set; }
public virtual Screen Screen { get; set; }
public virtual UserAction UserAction { get; set; }
}
public class RoleScreenActionPermission
{
public int RoleScreenActionPermissionID { get; set; }
public int ScreenActionID { get; set; }
public int RoleID { get; set; }
public virtual ScreenAction ScreenAction { get; set; }
public virtual Role Role { get; set; }
}
The talbe structure created is as:
Please help with setting the relationship correctly.
Try to remove all your own foreign keys from your classes. EF must make it.
upd:
public class Screen
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Action
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ScreenAction
{
public int Id { get; set; }
public virtual Screen Screen { get; set; }
public virtual Action Action { get; set; }
}
public class RoleScreenActionPermission
{
public int Id { get; set; }
public virtual ScreenAction ScreenAction { get; set; }
public virtual Role Role { get; set; }
}
I'm trying to eager load some child entities like so:
_context.Sites.Where(x => x.ID == siteID).Include(s => s.SiteLoggers).FirstOrDefault();
However, the error I am getting is:
A specified Include path is not valid. The EntityType 'MyProject.Dal.EF.Site' does not declare a navigation property with the name 'SiteLoggers'.
What is saying is correct, as MyProject.Dal.EF.Site does not exist, the object exists in MyProject.Domain.Entities.Site
What am I missing??? Thanks!
POCOs:
namespace MyProject.Domain.Entities
{
public class Site
{
public int ID { get; set; }
public int LocationID { get; set; }
public bool Active { get; set; }
public bool Deleted { get; set; }
public string Name { get; set; }
public virtual Location Location { get; set; }
public virtual IEnumerable<SiteLogger> SiteLoggers { get; set; }
}
}
namespace MyProject.Domain.Entities
{
public class SiteLogger
{
public int ID { get; set; }
public int UID { get; set; }
public int SiteID { get; set; }
public string Name { get; set; }
public int LocationID { get; set; }
public bool Active { get; set; }
public bool Deleted { get; set; }
public virtual Site Site { get; set; }
public virtual Location Location { get; set; }
}
}
You need to use ICollection instead of IEnumerable, because EF requires that your navigation properties are defined as ICollection<T>.
public virtual ICollection <SiteLogger> SiteLoggers { get; set; }