Following the ForeignKey docs, and multiple examples online I was under the influence that if I give my property (foreign key) this attribute, it would get replaced in a Html.Display call by the first textual property of the parent table.
This doesn't happen and all I get is the same foreign key field.
Does this work in db first applications, and if so, how do I make it work (using ForeignKey)?
Thanks.
EDIT: Or is this Scaffolding exclusive behaviour?
UPDATE: Example code:
// Entity model in Case.cs
public partial class Case
{
public int ID {get; set;}
public string Description {get; set;}
public int Classification_ID {get; set;}
public virtual Classification Classification {get; set;}
}
// Entity model in Classification.cs
// It's a lookup table
public partial class Classification
{
public int ID {get; set;}
public string Label {get; set;}
}
// File with partials
[MetadataType(typeof(CaseMetadata))]
public partial class {}
public class CaseMetadata
{
[ForeignKey("Classification")]
public int Classification_ID {get; set;}
}
Related
New to .NET core here. Trying to create a model structure to accommodate the following:
A single table, jobs, with a jsonb column in postgres
Multiple types of jobs, each of which will have a certain 'type' column string
Each job type will have it's own validation on the json column
Right now, I have two models. JobsServer.Models.Job and JobsServer.Models.SubJobCategory.SpecificJob. The look like this:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace JobsServer.Models
{
[Table("jobs")]
public class Job
{
[Column("id"), Key, Required, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get; set;}
[Column("type"), Required]
public string Type {get; set;}
[Column("domain"), Required]
public string Domain {get; set;}
[Column("status"), Required]
public string Status {get; set;}
[Column("data", TypeName = "jsonb")]
public string Data {get; set;}
[Column("rescheduled_from_id")]
public int RescheduledFromId {get; set;}
[ForeignKey("RescheduledFromId")]
public Job RescheduledFrom {get; set;}
[Column("parent_job_id")]
public int ParentJobId {get; set;}
[ForeignKey("ParentJobId")]
public Job ParentJob {get; set;}
}
}
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using JobsServer.Models;
namespace JobsServer.Models.SubJobCategory
{
[Table("jobs")]
public class SpecificJob
{
[Column("id"), Key, Required, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get; set;}
[Column("type"), Required]
public string Type {get; set;}
[Column("domain"), Required]
public string Domain {get; set;}
[Column("status"), Required]
public string Status {get; set;}
[Column("data", TypeName = "jsonb")]
public string Data {get; set;}
[Column("rescheduled_from_id")]
public int RescheduledFromId {get; set;}
[ForeignKey("RescheduledFromId")]
public Job RescheduledFrom {get; set;}
[Column("parent_job_id")]
public int ParentJobId {get; set;}
[ForeignKey("ParentJobId")]
public Job ParentJob {get; set;}
}
}
I then have a job context that looks like this:
using Microsoft.EntityFrameworkCore;
using JobsServer.Models;
namespace JobsServer.Contexts
{
public class JobContext : DbContext
{
public JobContext(DbContextOptions<JobContext> options) : base(options)
{}
public DbSet<Job> Jobs {get; set;}
public DbSet<JobsServer.Models.SubJobCategory.SpecificJob> SpecificJob {get; set;}
}
}
This gives me the error:
Cannot use table 'jobs' for entity type 'Job' since it is being used for entity type 'SpecificJob' and there is no relationship between their primary keys.
I'm probably going about this the wrong way. I'm coming from a ruby on rails and primarily elixir background, where I can accomplish what I'm trying to do here.
Essentially, if a user submits a post for creating a SpecificJob, I plan to set type to 'specific_job' and then validate the data json to match a certain format. There will be multiple types of jobs, of course, but the above is a simplified version to test the architecture.
Any assistance or ideas appreciated.
The EF pattern you are likely looking for is Table-per-Hierarchy, where you use inheritance to differentiate types of jobs, represented in a single job table with a discriminator. ("Type")
You should find all you need here:
https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph
I would like to create bidirectional links to the same class. Id like for the relationship class to have the attributes that would explain how the two classes are related. It may be a parent-child relationship or it be a simple "reference" relationship.
Currently, if I use the setup below, Entity Framework will automatically create a 3rd foreign key in the link table for the "myChildNodes" relationship. The only way I can get Entity Framework to understand what I am trying to do on the link class is to create two collections I.E. (childOf and ParentOf).
I would like to dynamically add relationship types and not need to create a collection representing that relationship type. I would rather handle that in the repository for the node object.
Node
{
Public int id {get; set;}
Public datetime createDate {get; set;}
Public bool isModified {get; set;}
//I would like just one collection for all links from this node as the source node
Public virtual ICollection<Link> myChildNodes{get; set;}
//I don't want to use something like this that explicitly defines the relationship
//Public virtual ICollection<Node> parentOf{get; set;}
//Public virtual ICollection<Node> childOf{get; set;}
Public Node() {
}
}
Link {
Public int id {get; set;}
Public datetime createdDate {get; set;}
Public string linkType {get; set;}
[ForeignKey("SourceNode")]
Public int? SourceNodeId { get; set;}
Public Node SourceNode {get; set;}
[ForeignKey("TargetNode")]
Public int? TargetNodeId { get; set;}
Public Node TargetNode {get; set;}
Public Link() {
}
}
Has anyone had success with this design before?
I'm not very experienced with EF and I'm trying to figure out what is the proper way or what are the options for creating entity, collection of which can be contained in other entities (different tables).
Let's say I have three existing classes (ModuleA, ModuleB, ModuleD) that I want to contain its own collection of Data entities.
I wanted a single table for Data entities but I don't like the idea of three nullable Guid columns for each FK.
That also gives me error on applying migration ("...may cause cycles or multiple cascade paths") - which could by probably solved by removing cascade delete and deleting Data manually, but I don't like that idea.
What I would like most is the single (shared) Guid property on Data for FKs to all three modules, which is not possible at least not without same ID existing in all three main tables at the same time (since it creates three FKs in DB).
class Data
{
public int Id {get; set;}
public byte[] Values {get; set;}
}
class ModuleA
{
public Guid Id {get; set;}
public ICollection<Data> Data {get; set;}
// some other stuff...
}
class ModuleB
{
public Guid Id {get; set;}
public ICollection<Data> Data {get; set;}
// ...
}
class ModuleC
{
public Guid Id {get; set;}
public ICollection<Data> Data {get; set;}
// some different other stuff...
}
You can create 3 module-to-data many-to-many tables like this:
class Data
{
public int Id {get; set;}
public byte[] Values {get; set;}
}
class ModuleAData
{
public ModuleAId {get; set;}
public DataId {get; set;}
}
class ModuleA
{
public Guid Id {get; set;}
public ICollection<ModuleAData> Data {get; set;}
// some other stuff...
}
I'm using Entity Framework 6.
I'm curious what is the reason for most entities I've seen around to contain their father entity.
Example:
Say I have the following models:
public interface IBaseEntityObject
{
public int Id {get; set;}
}
public abstract class BaseEntityObject : IBaseEntityObject
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get; set;}
}
public class Folder : BaseEntityObject
{
[DataMember]
public string Name {get; set;}
[DataMember]
public List<Letter> Letters {get; set;}
}
public abstract class Letter : BaseEntityObject
{
[DataMember]
public string Title {get; set;}
[DataMember]
public string Content {get; set;}
public virtual Folder Folder {get; set;}
[DataMember]
public int FolderId {get; set;}
[DataMember]
public DateTime CreationDate {get; set;}
}
public class OutgoingLetter : Letter
{
// .. OutgoingLetter properties
}
public class ReceviedLetter : Letter
{
// .. ReceviedLetter properties
}
I've seen this in all examples and demos of EF - containing the father model inside the child object - in my models it refers to contains Folder inside a letter. This seems logically incorrect to me, and break the oop design style.
Is there a specific reason for this? Because both me and my teammates are disturbed by this models design
Link from child to parent allows you to query child by parent data. For example in your case:
var lettersFromFolderOne = dbContext.Letters
.Where(letter => letter.Folder.CreationDate == DateTime.Now)
.ToList();
So look at it from db tables perspective and how you may need to build a query.
I have a Class like this:
class ClassA
{
public long classAID {get; set;}
public string Description {get; set;}
public IEnumerable<ClassB> ClassBs {get; set;}
}
class ClassB
{
public long classBID {get; set;}
public string SomeOtherDescription {get; set;}
public IEnumerable<ClassA> {get; set;}
}
class TestContext: DBContext
{
public DbSet<ClassA> ClassAs {get; set;}
public DbSet<ClassB> ClassBs {get; set;}
}
H have the DB with same column names and table names as the classes and properties.
I have done the web.config configuration as required. When i try to use above to retrieve the data i get the error
"System.Data.Edm.EdmEntityType: : EntityType 'ClassA' has no key defined. Define the key for this EntityType."
and
"System.Data.Edm.EdmEntityType: : EntityType 'ClassB' has no key defined. Define the key for this EntityType."
I tired multiple approaches such as setting the key attribute, Foreign key attribute etc. but nothing worked. Please let me know what am i missing.
I use C# 4 and i have verified with following URLs:
http://www.asp.net/mvc/tutorials/mvc-music-store-part-4
http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx
Use this:
public class ClassA
{
public long ClassAID {get; set;}
public string Description {get; set;}
public virtual ICollection<ClassB> ClassBs {get; set;}
}
public class ClassB
{
public long ClassBID {get; set;}
public string SomeOtherDescription {get; set;}
public virtual ICollection<ClassA> {get; set;}
}
public class TestContext: DBContext
{
public DbSet<ClassA> ClassAs { get; set; }
public DbSet<ClassB> ClassBs { get; set; }
}
As you can see navigation properties are marked as virtual. It will allow lazy loading = navigation property will be loaded separately first time your code access the property. It is not always the best way to load navigation properties this way because it causes additional roundtrips to the database. Because of that EF also offers eager loading where you explicitly tell EF to load your navigation property:
var query = context.ClassAs.Include(c => ClassBs);