I have two models.
BdoSubSystem:
public class BdoSubSystem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
}
And BdoSystem:
public class BdoSystem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<BdoSubSystem> SubSystems { get; set; }
}
I used migration to create the tables automatically on Azure. The problem is that subsystem is not specific for each system, a subsystem may have multiple parents and can appear in more than one system. But in this way, each subsystem belongs to each system.
How can a subsystem appear in multiple systems?
Good, thanks you all. The solution is to reference in subsystem and use [JsonIgnore]
public class BdoSubSystem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public virtual ICollection<BdoSystem> SubSystems { get; set; }
}
If I well understand, SubSystem is just a king of System that with a System as parent ?
If my sentence is true, you can use Self Referencing
public class BdoSystem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int? ParentSystemId { get; set; }
public virtual BdoSystem ParentSystem { get; set; }
}
However, if you want to have two seperates objects, you should add the navigation propertie in both classes
public class BdoSubSystem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<BdoSystem> Systems { get; set; }
}
public class BdoSystem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<BdoSubSystem> SubSystems { get; set; }
}
Related
I'm a little new to code-first in EF Core and I'm trying a few things out and I'm a little confused how to implement the below (or indeed whether it can be implemented or not).
In my model I have a class that maps entities to cases, with the following mapping class
public class CaseEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CaseEntityId { get; set; }
public int CaseId { get; set; }
public CaseModel Case { get; set; }
public Guid EntityId { get; set; }
public EntityModel Entity { get; set; }
}
I am now implementing the EntityModel object. However an entity can be either a Person or a Company. Both these have common properties, but there are some natural differences. What I wanted to do is create an IEntityModel interface and two classes as below
public class CaseEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CaseEntityId { get; set; }
public int CaseId { get; set; }
public CaseModel Case { get; set; }
public Guid EntityId { get; set; }
public IEntityModel Entity { get; set; }
}
public interface IEntityModel
{
Guid EntityId { get; set; }
PostalAddress PrincipalAddress { get; set; }
}
public class CompanyEntity : IEntityModel
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid EntityId { get; set; }
public string CompanyName { get; set; }
public PostalAddress PrincipalAddress { get; set; }
}
public class PersonEntity : IEntityModel
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid EntityId { get; set; }
public PostalAddress PrincipalAddress { get; set; }
public string FirstNames { get; set; }
public string Surname { get; set; }
}
When I try to build this I get the error
The property 'CaseEntity.Entity' is of an interface type ('IEntityModel'). If it is a navigation, manually configure the relationship for this property by casting it to a mapped entity type.
Otherwise, ignore the property using the [NotMapped] attribute or 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
I'm not 100% certain I can do what I'm trying to do. Searching around has left me a little confused (is that a solution to implement kind of functionality like, or should I use implement an entity class that has all the properties need to support a Company or a Person?)
I think it would be better if you create a base class
public class EntityModel:IEntityModel
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EntityId { get; set; }
publlic PostalAddress PrincipalAddress { get; set; }
}
CompanyEntity
public class CompanyEntity : EntityModel
{
public string CompanyName { get; set; }
}
CaseEntity
public class CaseEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CaseEntityId { get; set; }
public int CaseId { get; set; }
public CaseModel Case { get; set; }
public int EntityId { get; set; }
public virtual EntityModel EntityModel { get; set; }
}
This is for EF 6. So I have these 2 objects: User can have 0 or 1 Mechanic:
public class User
{
public int Id { get; set; }
public virtual Mechanic Mechanic { get; set; }
}
public class Mechanic
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Key, ForeignKey("User")]
public int UserId { get; set; }
[Required]
public virtual User User { get; set; }
}
This is the only way I found to go about it when I need its own Id in Mechanic object, but apparently it cannot serve as a Primary Key, so I'm just making it an auto-incremented identity column. Now this is a good work-around for 1 to 0 or 1 relationship.
However, there are flaws. I need to have another object PricePackages that is dependent on Mechanic, so now my objects are:
public partial class Mechanic
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Key, ForeignKey("User")]
public int UserId { get; set; }
[Required]
public virtual User User { get; set; }
public virtual ICollection<PricePackage> PricePackages { get; set; }
}
public class PricePackage
{
public int Id { get; set; }
[ForeignKey("Mechanic")]
public int MechanicId { get; set; }
public virtual Mechanic Mechanic { get; set; }
}
This works fine, however when I insert into PricePackage, the MechanicId is actually a Mechanic.UserId, and not Mechanic.Id that I want. How do I fix that?
I've got a little problem with my database design in an EntityFramework6 project. These are my two code first classes I use to create the database with. As you can see the Details class violates all normal forms out there and I want to split it up properly, however I have no idea how to do it properly, since I am totally new to SQLServer and EF.
So what is the best way to get a decent database design which I then could query?
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationsDetailsDataContract Details { get; set; }
}
internal class LocationDetailsDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }
public string Planet { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
public string System { get; set; }
public string Sector { get; set; }
public LocationDataContract Location { get; set; }
}
Updated Question below
So following the advice of George I did the following. Would this be a decent solution. I Have to add, that I need to to some converting since the application uses different (completely inheritance based) models, which I have to use since a database is not the only source of data and said data uses yet another format to store data which I can't change.
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationsDetails Details { get; set; }
}
internal abstract class LocationDetailDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }}
public LocationsDetails Details { get; set; }
}
internal class CityDetailDataContract : LocationDetailDataContract
{
public string Planet { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
}
internal class PlantDetailDataContract : LocationDetailDataContract
{
public int Population { get; set; }
public string System { get; set; }
}
internal class SystemDetailDataContract : LocationDetailDataContract
{
public string Sector { get; set; }
}
internal class SectorDetailDataContract : LocationDetailDataContract
{
// For now nothing
}
#Ruhrpottpatriot, why all classe are inheriting from LocationDetailDataContract?
Doing this i believe you will have a buch of classes and tables but the data will remain desnormalized (ex: CityDetailDataContract will have the column Planet with repeated strings.
Are you allowed to do something like this from you original question?
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationDetailsDataContract Details { get; set; }
}
internal class LocationDetailsDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }
public Planet Planet { get; set; }
public System System { get; set; }
public Sector Sector { get; set; }
[Required]
public LocationDataContract Location { get; set; }
}
internal class Planet {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
}
internal class System {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
internal class Sector {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
How can I build a model using Entity Framework to join 3 tables?
At the moment I have:
public class KeywordAdCategory
{
[Key]
[Column("Keyword_Id", Order = 0)]
public int Keyword_Id { get; set; }
[Key]
[Column("Ad_Id", Order = 1)]
public int Ad_Id { get; set; }
[Key]
[Column("Category_Id", Order = 2)]
public int Category_Id { get; set; }
}
But I don't have any navigation properties.
Is there a better way to build a relashionship between 3 tables using Entity Framework?
Also the Keyword, Ad and Category models:
public class Keyword
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Ad
{
// Primary properties
[Key]
public int Id { get; set; }
// Navigation properties
public AdOperation AdOperation { get; set; }
public Member Member { get; set; }
public Address Address { get; set; }
public Category Category { get; set; }
public virtual ICollection<Picture> Pictures { get; set; }
private ICollection<Feature> _features;
public virtual ICollection<Feature> Features
{
get { return _features ?? (_features = new HashSet<Feature>()); }
set { _features = value; }
}
}
public class Category
{
// Primary properties
public int Id { get; set; }
public int? CategoryParent_Id { get; set; }
public int? CategoryGroup_Id { get; set; }
public bool IsActive { get; set; }
// Navigation properties
public Keyword Keyword { get; set; }
}
Thanks.
I'm assuming that you're using Code-First Entity Framework here, and that you have your KeywordAdCategory object in your database as well. In which case, just simply do the following in your KeywordAdCategory class to do the proper mapping:
[Key, ForeignKey("Keyword")]
[Column("Keyword_Id", Order = 0)]
public int Keyword_Id { get; set; }
[Key, ForeignKey("Ad")]
[Column("Ad_Id", Order = 1)]
public int Ad_Id { get; set; }
[Key, ForeignKey("Category")]
[Column("Category_Id", Order = 2)]
public int Category_Id { get; set; }
public virtual Keyword Keyword { get; set; }
public virtual Ad Ad { get; set; }
public virtual Category Category { get; set; }
Doing this should do the proper mappings, put FKs on your KeywordAdCategory table, and thus give you the ability to have good navigation properties to the other objects.
So I have the following EF models:
[Table("Site")]
public class Store{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[ForeignKey("ID")]
public virtual ICollection<Item> Items { get; set; }
}
[Table("Item")]
public class Item {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Column("SiteID")]
public int storeID { get; set; }
[ForeignKey("storeID")]
public Store store { get; set; }
}
So, going from Item->Store seem to be fine, the data populate. But Store->Items doesn't populate. What am I doing wrong?
Figure it out, to build a one-to-many relationship, you need to use the InverseProperty. Like this!
[Table("Site")]
public class Store {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[InverseProperty("store")]
public virtual ICollection<Item> Items { get; set; }
}
[Table("Item")]
public class Item {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Column("SiteID")]
public int storeID { get; set; }
[ForeignKey("storeID")]
public Store store { get; set; }
}
Everything load, event the Items collection.