Add Navigation Property when column already exists - entity-framework

How can I add a navigation property to my context, when the corresponding column has already been created in the database from a previous migration?
For example: A lady has many cats. I want to add a LadyId property to the Cats class, but a LadyId column already exists in the Cats table. This LadyId column was created in a previous migration to accommodate the Cats.Lady navigation property.
DB:
Lady Table
--------------
Id Name
Cats Table
--------------
Id LadyId FurColor
Classes:
public class Lady {
public Id {get; set;}
public Name {get; set;}
public List<Cat> Cats {get; set;}
}
public class Cat {
public Id {get; set;}
public Lady Lady {get; set;}
//I want to add a LadyId property here
}
So far, I've tried...
Adding the property: Error: "The model backing the 'Context' context has changed..."
Adding a migration to update the DB: This creates a migration, but it just renames the column to LadyId1, which is pointless. The DB should remain the same, I just want to add a Navigation Property.
Commenting out code in migration Up and Down methods to try and "trick" the migration table into having the correct hash to match my context. This throws an error "Invalid column name 'EmployeePerformanceReview_id1"

Related

What is the best practice regarding setting Id's of contained entities in entity framework core

Assuming i have the following entities that i store in a database using entity framework core
public class Container{
public int ContainerId {get; set;}
public int ContainedId {get; set;}
public Contained Contained {get; set;}
}
public class Contained {
public int ContainedId {get; set;}
public int ValueA {get; set;}
public int ValueB {get; set;}
}
if at some point in time i decide to save a Container class, with a know Contained class should i manually set the Id?
var containerToSave = new Container{
Contained = contained;
ContainedId = contained.ContainedId
}
or this is a bad practice? If I set it with an id that doesnt match the one in the actual class what will it save?
As far as Entity Framework goes you can specify either a foreign key or add the related entity when saving the main one.
To answer your question... No, is not a bad practice and this isn't related to the EF either. Rather your Container matches the Contained is a business related problem and should be treated and validated there. EF role in your case is to save the data whatever method you choose.
Assuming you mark the Contained EF will give you 2 choices:
public virtual Contained Contained { get; set; }
Add the foreign key:
var containerToSave = new Container
{
ContainedId = contained.ContainedId
}
Add the entity itself:
var containerToSave = new Container
{
Contained = new Contained
{
ValueA = x;
ValueB = y;
}
}
In you case, if you already have the Contained added, you can go with the first one but not the less, either of above methods are working just fine.

Table with with different fields depending on category

I have table that has these columns:
Id
Title
Description
CreateDateTime
CategoryId
Picture
quantity
Price
RentPrice
WantToExchange
NumberOfRoom
DepositPrice
Only the first 6 are required for each row and other column will be null based on entity category.
For example in cat1 only first 6 field and Price filled by user,and in cat2 only first 6 field and RentPrice, DepositPrice are filled, so after a while many column of table rows become a null
I see some solution in NopCommerce source code that used for store various product property in different language - there are entity called LocalizedProperty and storeEntityId, LanguageId, Name of entity, name of field and its value
it use
Expression<Func<T, TPropType>>
and PropertyInfo to get name of field, but I am searching for an easier way.
How can I redesign my entity?
If you'd have designed this object orientedly, you would probably have create a PictureDescription class, and a PicturePrice class, that would have the other properties.
Every PictureDescription would have zero or one PicturePrice object: a straightforward aggregation
If you want zero-or-one in a relational Database, then this is quite often done using two tables, with a foreign key from one table pointing to the other table.
See Entity Framework zero-or-one-to-one
class PictureDescription
{
public int Id {get; set;}
public string Title {get; set;}
...
// every PictureDescription has zero or one PicturePrice
public virtual PicturePrice PicturePrice {get; set;}
}
class PicturePrice
{
public int Id {get; set;}
public decimal Price {get; set;}
...
// every PicturePrice belongs to exactly one Picture, using foreign key
public int PictureDescriptionId {get; set;}
public virtual PictureDescription PictureDescription {get; set;}
}
This will be enough for entity framework to detect your columns and the relations between the tables. If you want to use fluent API, in DbContext.OnModelCreating:
// every PictureDescription has zero or one PicturePrice:
modelBuilder.Entity<PictureDescription>()
.HasOptional(description => description.PicturePrice)
.WithRequired(price => price.PictureDescription)
.HasForeignKey(price => price.PictureDescriptionId);

How to map table name to EF Entity?

I have been using EF Code First for 1 month. My project needs to work with many tables (over 100 tables of data) and they will be changed many times in the future. It hard to control and take time to add the migration.
So is there any solution to skip the add-migration step, just create the table in the database and create a mapping to the Entity?
Example:
In database I have a table like this:
CREATE TABLE dbo.MyTable
(
Id INT,
Name VARCHAR(255),
Description VARCHAR(1000)
);
I want to map it to the following entity:
public class MyEntity
{
public Id int {get; set;}
public Name string {get; set;}
public Description string {get; set;}
}
My expected solution is something like this:
CreateMap("dbo.MyTable", MyEntity)
Use the attribute System.ComponentModel.DataAnnotations.Schema.Table
[Table("MyTable")]
public class MyEntity
{
public Id int {get; set;}
public Name string {get; set;}
public Description string {get; set;}
}
If you don't actually want to run the migrations, I suggest create them anyway and comment out the relevant code before you run them. That way you will be well set up for the occassion when you do actually want to run them.
You can define the entity maps by overriding the method called OnModelCreating in your DbContext:
Then you can add some maps similar to:
modelBuilder.Entity<Order>(m => {
m.ToTable("MyTable", "dbo");
})
Info: https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables
EDIT: I don't like adding annotation directly to my entity as I prefer to centralize it in one place. Easier to manage. After all I guess it's a question of preferences :)

Map subclass to same table as parent class without discriminator

I am trying to map a subclass of an existing entity onto the same table as the parent entity, like so:
public class Parent
{
public int ID {get; set;}
public string Name {get; set;}
}
public class Child : Parent
{
public virtual ICollection<Foo> {get; set;}
}
The child entity is identical to the parent except that it contains some navigation properties; the reason the child class exists (instead of adding the navigation properties to the parent class) is that the parent class is closed for modification (different assembly).
Entity framework doesn't like me mapping these to the same database table, expecting a discriminator column. How can I tell EF that these are really the same entity (just that I want some extra navigation properties on the child)?
Put them on separate DbContext's. The EF model builder looks for collisions between entities / tables on the properties of it's own context, not others.

Recurrency problem Entity Framework

I'm working with EF 4.1 CTP5 and SQL Server 2008. I need to understand how to solve a recurrency problem. I have the following 2 classes:
public class Nation
{
public int ID {get; set;}
public string name {get;set;}
public List<NationAlly> NationAllies {get;set;}
}
public class NationAlly
{
public int ID {get; set;}
public int level {get;set;}
public Nation Owner {get; set;}
public Nation toNation {get;set;}
}
The entities are mapped to the database with two tables (Nations and NationAllies). Besides, there are two relationships. 1) From NationAllies.OwnerID to Nation.ID
2) From NationAllies.ToNationID to Nation.ID
When I try to retrieve an object of Nation type from my database, I access the DbContext class NationDB:
Nation selectedNation = ((nationDB.Nations.Include("NationAllies")).Where(m => m.name == "France")).FirstOrDefault();
The problem is that I get a selectedNation object which has a list of NationAllies but every NationAlly in the list has the field toNation = null.
First of all I would like the field toNation to retrieve the correct information from the database. How do I do this?
Then of course toNation will be connected with other NationAllies which on their turn will have an other Nation. How could possibly a recursive map be built? My idea is to navigate the map until a certain level, by querying the database in a specific way. Doing so, what would be the best approach to have good speed performance?
It looks like NationAllies is junction table with additional properties. The problem is that EF doesn't eager load nested navigation properties if you do not specify them explicitly in Include method. If you want to have toNation filled you must use
nationDB.Nations.Include("NationAllies.toNation")
or
nationDB.Nations.Include(n => n.NationAllies.Select(na => na.toNation))
You can also enable lazy loading. Make all your navigation properties virtual (toNation, NationOwner and NationAllies) and unless you close the context all properties will be loaded once you first access them.