InvalidOperationException: The entity type 'object' requires a key to be defined - entity-framework

Entity-framework 7.
[Table("Settings")]
public class Setting
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public object DefaultValue { get; set; }
public string Classification { get; set; }
public FacilitySettingOverride FacilitySettingOverride { get; set; }
}
[Table("FacilitySettingOverride")]
public class FacilitySettingOverride
{
[Key]
[ForeignKey("FacilityId")]
public int FacilityId { get; set; }
public object Value { get; set; }
[ForeignKey("SettingId")]
public int SettingId { get; set; }
public virtual ICollection<Setting> Settings { get; set; }
}
[Table("Facilities")]
public class Facility
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<FacilitySettingOverride> FacilitySettingOverrides { get; set; }
}
When run the code
private IEnumerable<FacilitySettingOverride> GetFacilityBandwidthSettings
{
get
{
List<FacilitySettingOverride> settingList;
using (SettingDbContext context = new SettingDbContext())
{
settingList = context.FacilitySettingOverride.ToList();
}
return settingList;
}
}
Then get the exception:
InvalidOperationException: The entity type 'object' requires a key to be defined.
The context is:
public class SettingDbContext : DbContext
{
public DbSet<Setting> Settings { get; set; }
public DbSet<FacilitySettingOverride> FacilitySettingOverride { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=13.53.63.74;Initial Catalog=AAAAA;User ID=sa;password=password);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
However if I change the object to string for Value or DefaultValue in POCO then no exception. But the type in the database is sql_variant. I have to use the type object.

It seems that Data annotations are not yet supported so you will need to use the Fluent API for configuration.
See: https://github.com/aspnet/EntityFramework/issues/1913#issuecomment-86662854

Related

EF Core 7 - error occurred: the entity type 'List<string>' requires a primary key to be defined

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.

Entity Framework database-first : how to add property to a model that will reference itself?

I am trying to create a Product table that will have a list of SubstitutionProducts that should reference other Product from the same table.
Model example :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsMissing { get; set; }
public ICollection<Product> SubstitutionProducts { get; set; }
}
It is better to include the parent ID in your model:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsMissing { get; set; }
public int? ParentId { get; set; }
public Product Parent { get; set; }
public ICollection<Product> SubStitutionProducts { get; set; }
}
This is how to configure DB schema via overriding OnModelCreatingmethod of your DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>().HasOne(x => x.Parent)
.WithMany(x => x.SubStitutionProducts)
.HasForeignKey(x => x.ParentId).IsRequired(false);
}

EF.core One to many referencing the same table

EF.core beginner here.
In my app I have Persons. These are connected to other persons (in that same table), and those connections have a 'level'. I've added a join table called connection to store who is connected to who and on what level. When trying to do an Add-migration i get the following error:
Unable to determine the relationship represented by navigation property 'Connection.Person' of type 'Person'. Either manually configure the relationship, or ignore this property from the model.
There is no problem on my other join tables that reference two different tables. What am i missing here?
I'm using EF.core 1.1, with .net 4.5, code below
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string NickName { get; set; }
public List<Connection> Connections { get; set; }
}
public class Connection
{
public int PersonId { get; set; }
public Person Person { get; set; }
public int SecondPersonId { get; set; }
public Person SecondPerson { get; set; }
public int ConnectionLevelId { get; set; } // connection Level
public ConnectionLevel Level { get; set; }
}
public class ConnectionLevel
{
public int Id { get; set; }
public string Name { get; set; }
//rights
}
public class testContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Connection> Connections { get; set; }
public DbSet<ConnectionLevel> ConnectionLevels { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=localhost\\SQLEXPRESS;Database=master;Trusted_Connection=True;");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Connection>().HasKey(s => new { s.PersonId, s.SecondPersonId });
base.OnModelCreating(modelBuilder);
}
}

Lookup table with EF Codefirst

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; }
}

Entity Framework Code First and Invalid Object Name Error

I have a composite table called ImporterState, that are tied to a table called Importer and State. The error happens here context.Importers.Include(q => q.States). Why is this happening?
{"Invalid object name 'ImporterStates'."}
[Table("HeadlineWebsiteImport", Schema = "GrassrootsHoops")]
public class Importer
{
public int Id { get; set; }
public string Name { get; set; }
public string RssUrl { get; set; }
public string Type { get; set; }
public string Keywords { get; set; }
public bool Active { get; set; }
public DateTime DateModified { get; set; }
public DateTime DateCreated { get; set; }
public int WebsiteId { get; set; }
public HeadlineWebsite Website { get; set; }
[InverseProperty("Importers")]
public ICollection<State> States { get; set; }
}
[Table("State", Schema = "GrassrootsHoops")]
public class State
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Abbr { get; set; }
[InverseProperty("States")]
public ICollection<Headline> Headlines { get; set; }
[InverseProperty("States")]
public ICollection<Importer> Importers { get; set; }
}
The many to many is not possible using attributes only.
try using something like:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Importer>()
.HasMany(i => i.States)
.WithMany(s => s.Importers)
.Map(m =>
{
m.MapLeftKey("ImporterId");
m.MapRightKey("StateId");
m.ToTable("ImporterState");
});
}