Delete row from many-to-many table (VB.Net, .edmx) - entity-framework

I have Users and Regions. A User can be assigned to any number of Regions.
To implement this I have a table of Users, a table of Regions, and a third table UserRegion which is just UserID, RegionID (both columns form the primary key and they have foreign key relationships to the User and Region tables).
Entity Framework does not import the UserRegion table into my data model, instead it creates a property of each User object which is a list of Regions, and another on each Region object which is a list of Users. This is very useful except that I can't figure out how to un-associate a User from a Region.
The below code
Dim db as New DatabaseContext
Dim user = db.Users.Where(stuff).First()
user.Regions.Clear()
db.SaveChanges()
produces this error:
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
How can get rid of the relationship rows I don't want anymore?

I figured this out.
The relationship needs to be removed from both sides. So the code should be:
user.Regions.Clear()
For Each r in db.Regions
r.Users.Remove(user)
Next
db.SaveChanges()
Now I have a zillion for loops peppering this function but oh well. Hopefully this helps someone.

Related

Does Entity Framework Core have an option to use a default value of 0 instead of null for non existent references?

If I have an object called Project that has a property called Creator and creator is a complex type, EF will automatically use the value null if the Creator property has not been assigned. Is it possible to instead use 0 instead of null in the database fields?
No, that would break Foreign Key Constraints on the database side, since there wouldn't be a Creator row with a primary key of 0 for the Project row's foreign key to point to.
In a relational database, at least those that respect foreign key constraints, every relationship between rows is represented as a pair of primary, and foreign keys. The database is designed to enforce that a foreign key always points to a valid primary key. It will prevent you from updating a FK field to a value that doesn't exist in the PK field. It will also yell at you for trying to delete the row that contains the PK as long as the FK still points to it (unless cascade-delete is turned on, but that gets complicated).
In theory, Entity Framework could probably be forced in to trying to do what you want, but the database would reject it, and EF would almost certainly have issues trying to retrieve rows with the 0/null value in it if it is configured to include navigation properties.

Foreign key from events table 1-1 0r many?

I'm likely overthinking a problem here and may well get downvoted but I'm prepared to take the hit. I'm building my first schema in a data warehouse.
2 tables: events and contacts:
events(id(pk), cid, other, fields, here)
contacts(id (pk), cid(fk), other, fields, here)
Someone visits our website and registers. A line item is generated in events column "id" and a "cid" for contacts is generated. A new record is added to contacts.
I have two questions:
Can I make the primary key of contacts cid? Thus the primary key is also a foreign key?
I'm using MySQL Workbench to create the schema. When I create the contacts table I am able to set the foreign key of cid and the cardinality as either 1-1 or 1-many. From the point of view of contacts table, is the relationship 1-1 or to many? There will only ever be 1 cid record in contacts but if that user does multiple things (like receive an email from us etc) they will appear multiple times in events table. So, logically 1-many. But when creating this in Workbench the relation line appears as though it's a 1-many relation with the many part being at contacts, not the other way around as desired. It should be the other way around?
What is the relationship between events.cid and contacts.cid?
If a user's registration results in a single contact_ record while each user visit to the web site (each Session started) results in an event_ record belonging to that user’s contact_ record, then you have a One-To-Many relationship.
`contact_` = parent table (the One)
`event_` = child table (the Many)
Notice how I boiled down that relationship into a single sentence. That should be your goal when doing analysis work to determine table structure.
Relationships are almost always defined as a link from a primary key on parent table to a foreign key on a child table.
How you define the primary key is up to you. First decide whether you want a natural key or a surrogate key. In my experience a natural key never works out as the values always eventually change.
If using a surrogate key, decide what type. The usual choices are an integer tied to an automatically incrementing sequence generator, or a UUID. If ever federating data with other databases or systems then UUID is the way to go. If using an integer, decide on size, with 32-bit integers handling a total of 2-4 billion records. A 64-bit integer can track 18 quintillion records.
The foreign key in child table is simply a copy of its assigned parent’s primary key value. So the foreign key must have same data type as that parent primary key.
If a particular parent record owns multiple records in the child table, each of those child records will carry a copy of that parent’s primary key. So if the user Susan has five events, her primary key value appears once in the contact_ table and that same value appears five times in the event_ table stored in the foreign key column.
If cid uniquely identifies each contact_ record amongst all the other contact_ records, then you have a primary key. No need to define another.

EF many to many with junction entity database first

I have a junction table with and idenity primary key columns to realize a many to many relationship. Visual Studio automatically detects it as a many to many relationship and the junction table is not an entity.
How can i realize it that also this table is generated as an entity? I need this for breeze.js .
You just need to add additional columns (or properties) to that table (or model).
You said that your table has acolumn named ID and it's the primary key withe IsIdentity set to true. It must works, I'm using this approach...
There must be a problem or missing with your table definition. However, if all are OK, just add a nullable column in your table and update your model from database. The problem will go away.

Entity Framework - Join table with composite key and a primary key

I am struggling with the way entity framework handles join tables, specifically because entity framework requires that a join table has a composite key composed of the primary keys on the two related entities I want the hold the relationship for. The problem here is that I need to hold a relationship to the relationship so to speak.
This may be a problem with my database design or equally due to my lack of understanding with EF. It is probably best illustrated through example (see below);
I have three tables each with a primary key:-
Table : DispatchChannel
{ *DispatchChannelID integer }
Table : Format
{ *FormatID integer }
Table : EventType
{ *EventTypeID integer }
The relationship between EventTypes and DispatchChannels is held in EventTypeDispatchChannels (see below) since this only contains a composite key it is not pulled through into our model and entity framework takes care of maintaining the relationship.
Table : EventTypeDispatchChannels
{ EventTypeID integer, DispatchChannelID integer
}
My problem now arises because for each combination of EventTypeID and DispatchChannelID I want to hold a list of available formats, this would be easy if my EventTypeDispatchChannels table had a primary key therefore my other join table would look like this;
Table : EventTypeDispatchChannelFormats
{ EventTypeDispatchChannelID integer, FormatID integer
}
The absence of a primary key on EventTypeDispatchChannels is where I am struggling to make this work, however if I had the key then entity framework no longer sees this as a linked entity.
I'm relatively new to C# so apologies if I have not explained this so well, but any advice would be appreciated.
The moment you want to give an association a more important role than just being a piece of string between two classes, the association becomes a first-class citizen of your domain and it's justified to make it part of the class model. It's also inevitable, but that's secondary.
So you should map EventTypeDispatchChannels to a class. The table could have its own simple primary key besides the two foreign keys. A simle PK is probably easier, so your table Format can do with a simple foreign key to EventTypeDispatchChannels for the one-to-many association.
You will lose the many to many feature to simply address dispatchChannel.Events. In stead you have to do
db.DispatchChannels.Where(d => d.DispatchChannelID == 1)
.SelectMany(d => d.EventTypeDispatchChannels)
.Select(ed => ed.Event)
On the other hand you have gained the possibility to create an association by just creating an EventTypeDispatchChannel and setting its primitive foreign key values. Many-to-many associations with a transparent junction table can only be set by adding objects to a collection (add an Event to dispatchChannel.Events). This means that the collection must be loaded and you need an Event object, which is more expensive in database round trips.

Delete related elements in 1:N relation and not only inserts null in the foreign key

I have the following class
public class ObjectA{
private List<ObjectB> list;
}
ObjectA and ObjectB are in 1:N relation.
I want to delete some of ObjectB instances and I use:
while (objectA.list.Any())
objectA.list.Remove(objectA.list.First());
List is of the relation table -
List<ObjectAobjectB>
In the Database I have defined therelation as a nullable foreign key otherwise I get
The operation failed: The relationship could not be changed because one or more of
the foreign-key properties is non-nullable. When a change is made to a relationship,
the related foreign-key property is set to a null value. If the foreign-key does not
support null values, a new relationship must be defined, the foreign-key property
must be assigned another non-null value, or the unrelated object must be deleted.
So now that it is Nullable foreign key,
When I run sql profiling I get the following:
exec sp_executesql N'update [Schem].[ClassB]
set [ClassAID] = null
where ([Id] = #0)
',N'#0 uniqueidentifier',#0='092CE959-370A-4785-AF4A-93A0E4952C59'
It just enters a null in the relation instead of deleting the object.
What am I doing wrong?
Thanks.
objectA.list.Remove(objectA.list.First()); is removing the relationship, not the actual entity. If you want to delete the objectB's from the database then you have to remove them from the context like so:
foreach(var item in objectA.list.ToList())
context.ObjectBs.Remove(item);
I think it is a case of Cascade Delete.
I'm not sure but I think you can set the cascade delete (in your application AND in your database) to allow EF to make deletion on cascade.
Maybe look at some documentation to find how to do that. It seems there is a lot of related questions on SO.
Example
Example2
Example3