Ef code first one to many relationship - entity-framework

How o define one to many relationship in EF with different primary and foreign key name
UPDATED
Public class Tb1
{
[Key]
public int ID{get; set;} // primary
**public int foreignKey{get; set;} //foreign key**
public string name{get; set;}
[Foreign("foreignKey")]
public virtual ICollection<Tb2> Tb2{ get; set; }
}
Public class Tb2
{
[Key]
public int ID {get; set;} //primary
public int tb1ID {get; set}
public string address {get; set;}
}
Here i want one to many relationsip on Primary key: foreignKey at TB1
foreign kye: tb1ID at TB2
HOW??

My Nomal approach would be to include the navigation property as well. So I would change Tb2 like this:
Public class Tb2
{
[Key]
public int ID {get; set;} //primary
public int Tb1ID {get; set;} //notice I changed case on this variable as well
public Tb1 Tb1 {get; set;} //this is the new variable
public string address {get; set;}
}
Code first should be able to automatically understand the relationship now. If you don't want the Tb1ID property, you can remove it, and it will still work out just fine.

Related

EF Core one-to-one relationship with string property as key

I am using entity framework core 5 query syntax. There are 3 classes which reflect the tables in database.
public class Record { public int RecordID {get; set;} public decimal Amount {get; set} public string AccountName {get; set;} }
public class Dimension { public int DimensionID {get; set;} public string DimensionSymbol {get; set;} }
public class DimensionName { public int ID {get; set;} public string Name {get; set;} }
public class RecordDto { public int ID {get; set;} public string DimensionName {get; set;} }
The aim is to find DimensionName foreach Record. The relationship is as follows. RecordID field is a foreign key for Dimension. So it is easy to find this relationship. The problem is with DimensionName. DimensionID is NOT a foreign key to DimensionName. The logical key is DimensionSymbol which sometimes is a simple text like "200.000B" and sometimes it represents the number like 190. If DimensionSymbol is 190 then this 190 reflects the ID in DimensionName.
My query is as follows.
var query = from r in context.Records
join d in context.Dimensions on r.RecordID equals d.DimensionID
join n in context.DimensionNames on int.Parse(d.DimensionSymbol)\>0 ? int.Parse(d.DimensionSymbol) : 0 equals n.ID
select new RecordDto
{
ID = r.RecordID,
DimensionName = n.Name
}
And it doesn't work. Could you please adjust the code so that it works? Maybe I should configure sth in OnConfiguring method.

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

EF 5.0 Multiplicity Error On Simple Mapping

I have the following domain objects:
public class Person
{
public int Id {get; set;}
public int? FatherId {get; set;}
public int? MotherId {get; set;}
public int? HomeChurchId {get; set;}
public int? BirthCountryId {get; set;}
public Parent Father {get; set;}
public Parent Mother {get; set;}
public Church HomeChurch {get; set;}
public Country BirthCountry {get; set;}
}
public class Parent
{
public int Id {get; set;}
...
}
public class Church
{
public int Id {get; set;}
...
}
public class Country
{
public int Id {get; set;}
...
}
When mapping Person, all of these properties are mapped pretty much the same way:
HasOptional(p => p.Father).WithMany().HasForeignKey(p => p.FatherId);
HasOptional(p => p.BirthCountry).WithMany().HasForeignKey(p => p.BirthCountryId);
...
The problem is, with BirthCountry I receive the following error when I try to query Person:
One or more validation errors were detected during model generation:
System.Data.Entity.Edm.EdmAssociationType: : Multiplicity conflicts with the
referential constraint in Role 'Person_BirthCountry_Target' in relationship
'Person_BirthCountry'. Because all of the properties in the Dependent Role are
non-nullable, multiplicity of the Principal Role must be '1'.
If I remove the BirthCountry property (and mapping) everything works fine. What is confusing to me is that BirthCountry is set up just like every other nullable property in Person. Why aren't the other properties giving me the same error?
Thanks for whatever help you can offer!
Ignorance is not bliss ... its just plain frustrating.
I finally realized that I had a [Required] attribute on BirthCountryId. This was causing the problem ... which totally makes sense. I can't tell EF that its optional and required at the same time.
Hope this saves someone else from the same frustration I went through.

Entity Framework code first not working

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