Entity framework6 one to one navigation property - mapping

How do I map a navigation property when there is no key of its parent in it?
I mean
There is a class Contract.
This is a contract of sale of a product and needs a product to exists. TB_Contract contains ProductId.
The Product exists without a contract and there isn't a ContractId on TB_product.
In some cases the product can be in more than one contract, that's why it has been modeled as a many to one in bd. But in our classes it must be one-to-one
public class Contract
{
...
public Product Product { get; set; }
...
}
public class Product
{
...
public Contract Contract { get; set; }
...
}
table tb_Contract
(
idContract,
idProduct
)
table tb_Product
(
idProduct,
description,
)
I want my class Product have the contract which it's linked to, if there is one.
I'm using code first. How to I map it on EF6?

There's no way to map this as a one-to-one association. It's a one-to-many association by design. So if anything, the design should change to make it one-to-one.
Entity Framework models one-to-one associations by a foreign key that's also a primary key. Any other way to have one-to-one associations is by enforcing them through business logic.
In code, this means that Product has a collection of Orders and a validation rule that checks the number of items in this collection.

Related

MVC - Linking two Models using a foreign key

How would I add a foreign key linking my Club class and my ClubEvent class together in a one-to-many relationship where Club is the parent class and ClubEvent is the child.
These are the models I am using
public class Club
{
// Class to manage a single Club
[Key]
public int ClubID { get; set;
}//end Club
public class ClubEvent
{
[Key]
public int EventID { get; set; }
}
I want to connect these two tables so I can add events for a club so I can display only the relevant events for each club
This is pretty basic MVC, and if you need help with this stuff in the future please complete this tutorial: http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application it is great!
Since ClubEvent is a 'child' of Club (meaning one club can have one or many events) you want to have the reference to the parent in the child. So, you will add a reference to clubEvent linking each instance of that object to the appropriate club. Add this to your ClubEvent Object..
public int ClubID {get; set;}
[ForeignKey("ClubID")]
public virtual Club Club {get;set;}
By adding the navigation property (virtual Club Club) you will be able to make a call to the parent object from the ClubEvent child. (club)this.ClubEvent.
displaying this is easily achieved by querying the ClubEvents table with the parent Club ID. Like:
var events = db.ClubEvents.Where(e => e.ClubID == id)
Where 'id' is the ClubID passed to the method in your controller.
Hope this helps, if you have any issues check this link out because it has great examples for every relation type in MVC.
http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application

set relationship in models without DB Context File

I am developing an app where i am using MVC in Presentation layer so I have to define model classes in it.....and because of that I want relationship in that models.
How can we define relationship in model without Dbcontext class file.
I don't exactly understand what you are asking for, but I will take a shot.
EF creates relationships in models by having a reference to the related model(s).
Say you have models Cart and Item. A Cart can contain many Items, and any one Item can only belong to one Cart. This would be a one-to-many relationship.
public class Cart
{
public int CartId {get;set;}
//other properties
public List<Item> Items {get;set;}
}
public class Item
{
public int ItemId {get;set;}
// other properties
public Cart Cart {get;set;}
}
So from your Cart class you can fetch any Items it contains, and from any of those Items you can get the Cart that contains them.
Again, not sure if this is what you are asking for, and this is very quickly thrown together, but hopefully it helps.

Fluent Nhibernate HasMany to One Table from Several Tables

I have an entity/class/table which is referenced from several other entities, and I use Fluent NHibernate to handle the ORM for me. In a few instances, it's a simple reference where I can store the foreign key ID as a column and handle the reference in that simple way, but in a few other instances I need to reference a list of these items, and it needs done for at least three classes I can think of. You can assume this setup will be copied to handle the other classes' relationships.
Here's how the common entity looks (the one that is owned by several other entities in HasManys):
public class Student {
public virtual int Id {get; set;}
public virtual string Name {get; set;}
}
And, here's what the ShopCourse entity looks like:
public class ShopCourse {
public virtual int Id {get; set;}
public virtual int Name {get; set;}
public virtual IList<Student> Students {get; set;}
}
Imagine that a couple other classes I have, such as specific courses, can "own" several students. In order to maintain that relationship I must create a table in my database that tracks the foreign keys between the two (for each entity that references Student) - no entity needed for this intermediate table, and Fluent won't need to think of it unless I hand it the string name of the table itself:
Table: ShopCourseStudents
int - ShopCourseId
int - StudentId
Lastly, here are my mappings. You can assume that the entities themselves map out fine - things such as the naming scheme for the Id are resolved and working correctly. The issue lies when I attempt to initialize any entity that has a HasMany of Student:
//Inside a FluentlyConfigure().Mappings(m => m.AutoMappings.Add() call:
.Override<ShopCourse>(map => {
map.HasMany(x => x.Students)
.Table("ShopCourseStudents")
.KeyColumns.Add("ShopCourseId")
.KeyColumns.Add("StudentId")
.Cascade.All();
})
The issue is that when I attempt to load a list of ShopCourses I get the Fluent error:
Foreign key (ABC123AF9:Student [ShopCourseId, StudentId]) must have
same number of columns as the referenced primary key (ShopCourses
[Id])
I do not override Fluent's mapping of Student as it's straightforward. For the purpose of this example, Student doesn't need to know which ShopCourses it belongs to, or any of the other courses that may own that particular Student record.
This seems like I'm doing something basic, wrong - what is it, exactly? Much obliged in advance!
So, the issue was with the custom code that I re-use with my projects, apparently the piece written to handle the ManyToMany convention is mostly broken. What I was looking for here was a ManyToMany relationship, not HasMany. The issue I had was that my code was forcing a reference on the child object (in this example, Student) to the parent, which I do not need and only complicates things. Removing that, and my ManyToMany then works:
.Override<ShopCourse>(map => {
map.HasManyToMany(x => x.Students)
.Table("ShopCourseStudents")
.ParentKeyColumn("ShopCourseId")
.ChildKeyColumn("StudentId")
.Cascade.All()

EntityFramework 4.3 Supertype Late Initialization

I'm using EF 4.3 with CodeFirst and I have a supertype/subtype model similar to this one:
public Person {
long Id { get; set; }
[Required]
string Name { get; set; }
}
public Costumer : Person {
string SomeData { get; set; }
[Required]
string SomeRequiredData { get; set; }
}
This is a simplified version of the problem. The tables have several fields.
A person can be a "promoted" to Costumer later in the application. So Person is created first and then transformed to Customer.
The question is: After I create Person how can I "promote" it to Vendor without creating (or recreating) a new Person record?
If I do:
var costumer = new Costumer {
Id = [same id used before when Person was created],
SomeRequiredData = "Data"
};
The model gives an error saying that Name is required. I should not be required to repeat all required info from Person in the new Vendor instance since it's already there in the original Person record.
Can anybody help?
P.S. The model is configured to create 2 separate tables, one for each class...
After I create Person how can I "promote" it to Vendor without
creating (or recreating) a new Person record?
You most can't with EF because you cannot change the type of existing instance (you cannot cast Person to Customer). Because you cannot cast the entity you also cannot update its type in the database with EF. In the same time you cannot insert Customer instance with existing Id because this operation expect inserting both parent and child type (remember Customer is a Person in your model and because of that inserting Customer means inserting Person as well).
The reason why it doesn't work is that your domain model is wrong. You should not have Customer as subtype of the Person because in OOP it means exactly what happened now - you cannot change person to customer without creating a new person instance (because customer is a person). To support this scenario you must have only Person entity and this entity must have property describing its type.

single entity for different tables

I have same type of tables
ProductCodeTable, CountrycodeTable etc
All have key, value as their fields
When I use entity frame work,
Can I have a single entity for all these tables such that I can formulate different queries to get data from different tables?
You can create a base class for all of them and create sub class for each entity
public abstract class LookUpEntity
{
[Key]
public int Key { get; set; }
[Required]
public string Value { get; set; }
}
[Table("ProductCodeTable")]
public class ProductCode : LookUpEntity
{
}
This way you can model the relationships also and later if you wanted to add specific properties to those look up entities with out affecting other entities.
You can create a view with a Union of all tables like this:
create view AllKeyTables as
SELECT 'Product' as table, Productkey as Key, nameProduct as name
FROM ProductCodeTable
UNION
SELECT 'Country' as table, CountryISO as key, CountryName as name
FROM CountrycodeTable
UNION
...
Then update EF model and check 'table' and 'key' fields as Entity Primary Key.
Next question you will do is: 'How can I make a relation between this Entity and existing Entities?' The answer is 'you can't because EF is not able to join Entities between other fields than primary key'. Then, before implement this solution, be sure that this is you are looking for.
EF supports this only if you model it as inheritance (#Eranga showed it in code-first approach). You will have single base entity and derived entity for each table so you will not avoid having different type for each table. Otherwise the answer is no.
Inheritance will put additional requirements on data in your tables. For example Ids will have to be unique among all tables. So if ProductTableCode will have record with Id 1, CountryCodeTable (and any other code table) mustn't have record with Id 1.
Also inheritance in EF can produce nasty and very poorly performing queries.

Resources