EF6 remove entry from joining table [duplicate] - entity-framework-6

This question already has answers here:
Removing many to many entity Framework
(2 answers)
Closed 3 years ago.
I have a many-to-many relation between customers (for example a company) and persons.
Adding new already stored persons to a company is working, but how do I delete an association between those 2, in case some person stops working in this company?
I don't want to delete the person or the company. Just the entry in my customer_person joining table.
Something like:
context.Entry(someCustomer.somePerson).State = System.Data.Entity.EntityState.Deleted;
deletes the person. That's not what I want.

the proper way of doing this is:
1st in your dbcontext add the cascade delete conventions.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Add<ManyToManyCascadeDeleteConvention>();
base.OnModelCreating(modelBuilder);
}
and then in your POCO classes the relations you don't want to delete
declare the properties either as string or int?depending on the master primary key type
example:
public int? personRefno {get;set;}
or
public string personRefno {get;set;}
when the type is nullable such as string or int? (note when you add question mark it means nullable)
EF does not delete the related record, keeps that and set the personRefno to null

Related

Why is my custom DbContext creating a table on insert?

I'm working on an ASP MVC project.
Here are the steps I followed :
I added entity framework in my project references
I connected to my SQL SERVER database and then copied the associated connection string in Web.config using this answer. The connection is successful
I created manually my own DbContex class. Below is its code :
public class MyConxtext : DbContext
{
public MyConxtext() : base("name = MyConnString"){}
public DbSet<user> user { get; set; }
}
Now user here not only is the name of my table user in SQL server but also is the name of my model user in my ASP MVC.
My problem is that :
- when I wanted to persist (several item in a session) via MyContext.SaveChanges(), it has created another table in my database named users ... Notice the plural here users... So instead of working on the table user, it created another table called users and persited data on that table.
My context also is not able to read data from the user table. BUT as I said it processes everything is the schema of the connection string
How can I solve that problem ?
Not only that it has also created another table in my schema called MigrationHistory which contain data about my project...
You can override OnModelCreating method in your DbContext and add the following line
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
This should remove pluralization for naming
Entity Framework by default pluralizes the table name when it generates it from the supplied entities.That means, if there is a class named Student as entity object and you declare a DbSet <Student> on your context (class inherited from DbContext), by default EF creates the table in a plural form of the entity name. This is a general concept as the table will contain several rows of that entity type, which refers it will be a collection of the entities, in our case it will make a table named Students.
If you want to remove this default convention (System.Data.Entity.ModelConfiguration.Conventions), you can override the method named
onModelCreating()
of DbContext class.
In your code you can do
public class MyConxtext : DbContext
{
public MyConxtext() : base("name = MyConnString"){}
public DbSet<user> user { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove < PluralizingTableNameConvention > ();
}
}
This will stop pluralizing the table's name in your database and it will use the user table of your database as you mentioned.

MVC 5 Scaffolding with inheritance uses the wrong entity set

With MVC 5 and EF 6.1 I am using a simple inheritance hierarchy, where class Student inherits from class Person. For both classes I have an entity set (DbSet property) in my database context:
public class DatabaseContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Student> Students { get; set; }
}
Now when I ask the scaffolder to generate a controller for Student, the subclass, it uses the Persons entity set, leading to statements such as
Student student = db.Persons.Find(id);
where the compiler obviously complains that it cannot just convert any Person to a Student.
Is there a way to make sure that the scaffolder uses the correct entity set (Students in this case)?
Note that removing the Persons entity set is not a good solution, because there are other controllers that need that.
Use find and replace to change all occurrences in the Controller class of the parent DBSet to the child DBSet eg change Persons to Students.
As you probably know (as I think you raised it) Microsoft have confirmed this is a known bug http://connect.microsoft.com/VisualStudio/feedbackdetail/view/945937/mvc-5-scaffolding-with-inheritance-uses-the-wrong-entity-set but they won't be fixing it.
Instead of inheritance why not use a relationship making personID the Foreign key ? That why you can db.students.find(personID)
And
db.person.find(personID)
To find all details ?
Extra code but I can't think of another way
You can use the command OfType<>, as shown:
Student student = db.Persons.OfType<Student>().SingleOrDefault(s => s.id == id);
This command works with inheritance. In this case, when Student inherits from Person.

How to delete all many-to-many relations without loading related entities in Entity Framework?

I have db scheme where Product table have many to many relation to Color table. I'm using EF and create POCO objects:
public class Product
{
public Guid Id {get;set;}
public ICollection<Color> Colors {get;set;}
}
public class Color
{
public Guid Id {get;set;}
public ICollection<Product> Products {get;set;}
}
In many situations it is necessary to delete all colors related to product and set new colors. So i want to delete all many to many relations whitout exactly knowing id of related colors. Is it possible to delete them without additional queries to db? I know i can just write stored procedure which will delete all relation with colors for specified product, but it will be better to find general approach through entity framework.
If you don't know keys of colors you cannot delete them without loading them first - EF deletes records one by one so it needs to know which record to delete.
The straight forward option is executing SQL DELETE directly:
dbContext.Database
.ExecuteSqlCommand("DELETE FROM dbo.ProductColors WHERE ProductId = #Id", product.Id);

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

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