Entity Framework code first not working - entity-framework

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

Related

ForeignKey Attribute in database first application

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

Automapper with reciprocal navigation properties

need a bit of help here.
I have a couple of classes that I am trying to map using Automapper. I am using EF core.
The basic domain is like this:
Public class A
{
public string Id {get; set;}
public string Name {get; set;}
public virtual Icollection<AB> AB {get; set;}
}
Public class B
{
public string Id {get; set;}
public string Name {get; set;}
public virtual ICollection<AB> AB {get; set;}
}
Public class AB
{
public string A_Id {get; set;}
public string B_Id {get; set;}
public virtual A A {get; set;}
}
My DTOs are like this:
Public class A_DTO
{
public string Id {get; set;}
public string Name {get; set;}
public ICollection<B> Bs {get; set;}
}
Public class B_DTO
{
public string Id {get; set;}
public string Name {get; set;}
public ICollection<A> As {get; set;}
}
Now where I get stuck is:
How to set up the mapping so that Automapper automatically retrieves the list of children (e.g the relevant 'Bs' for the current 'A')
How to configure my DTOs so that, for example, the retrieved 'Bs' for an 'A' do not expose the 'A's navigation property to prevent infinite recursion.
Thank you!
Partial answer here. I was researching and stumbled upon https://www.exceptionnotfound.net/entity-framework-and-wcf-loading-related-entities-with-automapper-and-reflection/
So I changed my DTOs by removing the navigation properties when the DTO is not the principal.
Public class A_DTO
{
public string Id {get; set;}
public string Name {get; set;}
}
Public class A_Nav_DTO: A_DTO
{
public ICollection<B> Bs {get; set;}
}
and in my mappings I did
CreateMap<A, A_DTO>();
CreateMap<A, A_Nav_DTO>()
.ForMember(dto => dto.B, map =>
map.MapFrom(model =>
model.AB.Select(ab => ab.B).ToList()));
Now this works, but obviously now I have to map three classes instead of two. Any suggestions on how to improve this solution?
I know it's an old question but hopefully this helps someone.
You could call Automapper's ResolveUsing method like so :
cfg.CreateMap<A, A_DTO>()
.ForMember(x => x.Bs,
opt => opt.ResolveUsing(src => RemoveInclusions(src)));
And in RemoveInclusions method you can manually set B's navigation of A's to null like :
private B RemoveInclusions(A src)
{
src.Bs.A = null;
return src.Bs;
}

Bidirectional links to the same class in Entity Framework (code first)

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?

Entity Framework Models

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.

Entity Framework Many to Many relationship with multiple keys

I'd like to add a table to define permission object than can be applied to many models.
To do this, I create a Permission class:
public class Permission
{
[Key]
int PermissionID {get; set;}
string User {get; set;}
bool Read {get; set;}
bool Write {get; set;}
}
And then other object classes than can have a List of Permission:
public class ObjectModel1
{
[Key]
int idObject1 {get; set;}
... Other properties ...
public virtual ICollection<Permission> Permission {get; set;}
}
public class ObjectModel2
{
[Key]
int idObject2 {get; set;}
... Other properties ...
public virtual ICollection<Permission> Permission {get; set;}
}
How can I obtaint a multiple many to many relationship between Permission and other Object classes without defining Foreign Keys in Permission class for each Object?
A many to many relationship will have an xref table between the two entities:
// because Permission has a collection to ObjectModel1 and ObjectModel1 has a collection
// to permission, it is treated as a many to many relationship with an implicit
// xref between the tables. The xref will contain a foreign key to each entity that is
// also a composite primary key
public class Permission
{
[Key]
int PermissionID {get; set;}
string User {get; set;}
bool Read {get; set;}
bool Write {get; set;}
public virtual ICollection<ObjectModel1> ObjectModel1s { get; set; }
public virtual ICollection<ObjectModel2> ObjectModel2s { get; set; }
}
public class ObjectModel1
{
[Key]
int idObject1 {get; set;}
... Other properties ...
public virtual ICollection<Permission> Permission {get; set;}
}
public class ObjectModel2
{
[Key]
int idObject2 {get; set;}
... Other properties ...
public virtual ICollection<Permission> Permission {get; set;}
}
Entity Framework will create a table that is something like PermissionObjectModel1 that has a composite primary key with two foreign keys (one to Permission, one to ObjectModel1). It will create another table for ObjectModel2 with similar keys. The foreign key doesn't exist on Permission itself.
If you don't want to have the navigation property on permission, then I think you will need to use the Fluent API:
public class MyDbContext : DbContext
{
public DbSet<Permission> Permissions { get; set; }
public DbSet<ObjectModel1> ObjectModel1s { get; set; }
public DbSet<ObjectModel2> ObjectModel2s { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ObjectModel1>()
.HasMany(many => many.Permissions)
.WithMany() // dont want navigation property on Permission
.Map(xref => xref.MapLeftKey("ObjectModel1Id")
.MapRightKey("PermissionId")
.ToTable("ObjectModel1PermissionXref"));
modelBuilder.Entity<ObjectModel2>()
.HasMany(many => many.Permissions)
.WithMany() // dont want navigation property on Permission
.Map(xref => xref.MapLeftKey("ObjectModel2Id")
.MapRightKey("PermissionId")
.ToTable("ObjectModel2PermissionXref"));
}
}
Something similar to the above code would still give you a many to many relationship, but the navigation property would not be defined on Permission.