EntityFramework Add to Many-To-Many - c#

I have a Vacation and a list of Countries. I whish to bind these together using a many-to-many relationship. I have a code-first Vacations model and Countries model. Both the individual tables aswell as the join table are successfully generated.
However, when I try to add a country to a vacation (or vice versa) the join table remains empty. I am able to successfully add the individual vacations aswell as the countries.
Models
public class Vacations
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int VacationId { get; set; }
public string ProductId { get; set; }
public string Name { get; set; }
public string Price { get; set; }
public virtual ICollection<Countries> Countries { get; set; }
public Vacations()
{
Countries = new List<Countries>();
}
}
public class Countries
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CountryID { get; set; }
public string CountryName { get; set; }
public virtual ICollection<Vacations> Vacations { get; set; }
public Countries()
{
Vacations = new List<Vacations>();
}
}
public class MyContext : DbContext
{
public MyContext()
: base("myconn")
{
}
public DbSet<Vacations> Vacations { get; set; }
public DbSet<Countries> Countries { get; set; }
}
Insert the Vacation
Vacations vacation = database.Vacations.Add(new Vacations
{
Name = vacationData.Name,
Description = vacationData.Description,
});
database.SaveChanges();
// to make sure the key is in the database to refrence
foreach (string country in AllMyCountries)
{
Countries countries = database.Countries.Add(new Countries
{
CountryName = country
});
countries.Vacations.Add(vacation);
vacation.Countries.Add(countries);
}
database.SaveChanges();
I have also tried just adding to one entity, and adding more calls to SaveChanges() inbetween.

Interesting problem in that your sample code all looks perfectly okay. Infact, I put a quick test together around this code and Entity Framework created the mapping table vacationscountries as expected and populated it correctly.
Just on the off-change, can you confirm that you are looking in the mapping table created by Entity Framework and not a custom mapping table? The only reason I mention it is that theres no way (that I know of) to map a many-to-many relationship to a custom junction table using Data Annotations.
If thats not the case, then the next thing I would do is to trace out the sql being generated by Entity Framework - either using your native database tracing tooling (e.g. Sql Profiler), a third party tool like EFProf, or through a logging interceptor ( http://msdn.microsoft.com/en-gb/data/dn469464.aspx ). Hopefully that will give some lower-level insights into the problem.

I re-created your Models but made some adjustments that generate the same results. I manually created the junction table VacationsCountries with the following code:
public class VacationsCountries
{
[Key, Column(Order = 0)]
public int VacationId { get; set; }
public virtual Vacations Vacation { get; set; }
[Key, Column(Order = 1)]
public int CountryId { get; set; }
public virtual Countries Country { get; set; }
}
I also added this line of code to the MyContext class:
public DbSet<VacationsCountries> VacationsCountries { get; set; }
Instead of using:
countries.Vacations.Add(vacation);
vacation.Countries.Add(countries);
I use:
VacationsCountries vc = database.VacationsCountries.Add(new VacationsCountries
{
Country = countries,
Vacation = vacation
});
and then call database.SaveChanges();
I checked the database and the entries were added to the VacationsCountries table.

Related

C# Entity Framework : Rename table field without losing data, using automatic migrations

I am using Entity Framework's automatic migrations with a code-first approach.
I dont use the packet manager console and dont have access to coded migrations.
I have a line representing my table in my model here :
public virtual DbSet<Customer> Customers { get; set; }
I renamed one of the fields of Customer :
[Table("Customers")]
public partial class Customer
{
[Key]
[Column(TypeName = "numeric")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int idCustomer { get; set; }
public string name { get; set; }
public int age { get; set; }
public string mail { get; set; }
public string password { get; set; }
}
I just changed "mail" to "mailModified".
But when the database got updated, Entity deleted all data from the name field.
I think it deleted my column to create a new one with the new name.
How to avoid that ? How to make him understand to only rename the column ?
Thanks for any participation
You have to do it using Migration commands.. so that data won't be lost ..
Else u can add the following code to auto-generated up and down method
RenameColumn("dbo.MyTable", "NewColumn", "OldColumn");
Try using Column Attribute when you create your table class
class Table
{
[Column("ColumnName")]
public int Column1 { get; set; }
[Column("ColumnName")]
public int Column2 { get; set; }
}

Entity Framework Joining Three Tables and Using Group Concat

I have three models like followings,
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Document
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Application { get; set; }
public ICollection<DocumentResponsible> DocumentResponsibles { get; set; }
public string Pcda { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
public class DocumentResponsible
{
public int Id { get; set; }
public int DocumentId { get; set; }
public int TeamId { get; set; }
}
I want to write an entity framework expression to join three table and select all fields of document table and team names in one row per documents. So basicly I want to join three table use group_concat for team names. Then I want to bind it to a gridview in web form.
What I have tried,
(from dc in DBContext.Document
join dr in DBContext.DocumentResponsible on dc.Id equals dr.DocumentId
join t in DBContext.Team on dr.TeamId equals t.Id
select new
{
Name = dc.Name,
Type = dc.Type,
Application = dc.Application,
Pcda = dc.Pcda,
}).ToList();
and I have just tried it,
var data = DBContext.Dcoument.Include("DocumentResponsibles").Tolist();
It's hard to help without your DbContext and the Entity Mappings, but I'll go out on a limb saying you might just want to mark Document.DocumentResponsibles as virtual.
Also, in DocumentResponsible, maybe you'd want to add a property for Document and one for Team (both marked as virtual too) this way you don't have to do the join keys all the time you want to work with your data, EF would do it for you once properly configured.
If it doesn't work, can you add the following information to your question: First, the context class and the mappings you have. Second, if you do var firstDocument = yoneylemDB.Document.First(), how does firstDocument looks like? Does it have all it's fields and properties filled out? Is there anything weird?

Am I building the wrong entities in MVC?

Goal. I have a "Gift" entity that describes what someone has to offer (babysitting, dog walking, etc) with a rating. And I want a "GiftCategory" entity that gives general category descriptive information (pets, sports, automotive, etc) for someone to search apon and then get all gift that have those categories. A "Gift" entity can have multiple "GiftCategory" entities associated with it. I want the ability to search for a category and pull out all "Gift" entities that have been created with those categories associated with them. Here is what I have so far but it doesn't seem to work with the entity first approach. Maybe I need another table that connects the two entities because currently the way the two tables are connected doesn't seem correct?
Gift entity:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
Category entity:
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The "GiftCategory" table that gets created creates a gift_id column that links the "GiftCategory" back to a gift (not what I want)!!!!
It seems like I would need to create a entity that connects the two entities? Something like:
public class ConnectGifts
{
public int Id { get; set; }
public string GiftId{ get; set; }
public string GiftCategoryID{ get; set; }
}
This way I can have multiple categories for a Gift, but the thing I don't understand is with entity first I really don't need this entity I just need what would be this table to get/query the "GiftCategory" entities for ids then get the gift ids to get all the gifts. So it seems like creating this entity is overkill? Is there a way to do it without creating a third table/entity ("ConnectGifts") with code first? Or am I not understanding that all entities are tables and all tables are entities? I'm also using linq-to-sql for all querying.
You're looking for a many-to-many relationship and can be defined as:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Gift> Gifts { get; set; }
}
So each has a collection of the other. Gift has many Categories and Category had many Gifts. You could use a bridge table like you've done with ConnectGifts but it's not necessary with EF. Using just Gift and GiftCategory, EF will actually create the bridge table for you.

2 POCO's with inheritance creates one table instead of two

I am creating a fairly simplistic Database for a holiday system.
Entities
Employee
public class Employee
{
public int Id { get; set;}
public string Username { get; set; }
public LineManger Manager { get; set; }
}
LineManger
public class LineManager : Employee
{
public string CompanySection { get; set; }
}
Relationship
As you can see, each employee has one LineManger however an Employee could be a LineManager.
In my DbContext I have:
public DbSet<Employee> Employees { get; set; }
public DbSet<LineManager> Managers { get; set; }
public DbSet<HolidayConfiguration> Configurations { get; set; }
public DbSet<Holiday> Holidays { get; set; }
When I ran PM > Update-Database -verbose for the first time it only created an Employee table and this table has CompanySection and Manager_Id which doesn't map to anywhere seeing as there isn't a LineManager table.
Any explanations on why this has happened? Is this correct?
It has to be like this, because every LineManager is an Employee, so when you are querying Employees you are also looking for LineManager. DbSet<Employee> Employees matches only one table, so the only way how EF can create table is to put in it all fields from LineManager.
Sometime (when you have more inhertiance) EF create special column in which it puts class name.

entity framework - many to many relationship

Hi I try use Many to Many relationship with EF Fluent API. I have 2 POCO classes.
public class Project
{
public int ProjectId { get; set; }
public virtual ICollection<Author> Authors { get; set; }
public Project()
{
Authors = new List<Author>();
}
}
public class Author
{
public int AuthorId { get; set; }
public virtual ICollection<Project> Projects { get; set; }
public Author()
{
Projects = new List<Project>();
}
}
And I map many to many relationship with this part of code:
////MANY TO MANY
modelBuilder.Entity<Project>()
.HasMany<Author>(a => a.Authors)
.WithMany(p => p.Projects)
.Map(m =>
{
m.ToTable("ProjectAuthors");
m.MapLeftKey("ProjectId");
m.MapRightKey("AuthorId");
});
This created table ProjectsAuthors in DB. It is my first attempt with this case of relationship mapping.
If I omitted this mapping it created table AuthorProject with similar schema. It is correct bevahior?
By trial and error I found the following. Given two classes...
public class AClass
{
public int Id { get; set; }
public ICollection<BClass> BClasses { get; set; }
}
public class BClass
{
public int Id { get; set; }
public ICollection<AClass> AClasses { get; set; }
}
...and no Fluent mapping and a DbContext like this...
public class MyContext : DbContext
{
public DbSet<AClass> AClasses { get; set; }
public DbSet<BClass> BClasses { get; set; }
}
...the name of the created join table is BClassAClasses. If I change the order of the sets...
public class MyContext : DbContext
{
public DbSet<BClass> BClasses { get; set; }
public DbSet<AClass> AClasses { get; set; }
}
...the name of the created join table changes to AClassBClasses and the order of the key columns in the table changes as well. So, the name of the join table and the order of the key columns seems to depend on the order in which the entity classes are "loaded" into the model - which can be the order of the DbSet declarations or another order if more relationship are involved - for example some other entity refering to AClass.
In the end, it doesn't matter at all, because such a many-to-many relationship is "symmetric". If you want to have your own name of the join table, you can specify it in Fluent API as you already did.
So, to your question: Yes, naming the join table AuthorProjects is correct behaviour. If the name had been ProjectAuthors it would be correct behaviour as well though.

Categories

Resources