How to update the cross reference table? - c#

In EF cross reference tables are abstracted away by creating many-to-many relationships. E.G.
There's a SQL table dbo.TrialContactCrossReference that relates TrialContactId to TrialID. Now, EF did not generate an Entity TrialContactCrossReference because it went with this MANY-MANY relationship thing. How do I add a new row to said table?
I tried
context.TrialContacts.??? and context.ClinicalTrials.??? and just don't know what to do with this. If I have a new Contact that I want to relate to a trial how am I supposed to go about it?

trial.Contacts.Add(contact);
OR
contact.Trials.Add(trial);
OR (and my advise)
you could create an additional entity for cross reference table. this will convert many-many to 2 one-many relationships. more then %90 cases crosstables has additional columns (at least IsActive, RecordDate etc.) even it doesnt, it may be so in future and it requires you make lots of changes in code.

If I have a new Contact that I want to relate to a trial how am I supposed to go about it?
Assuming you have an existing Contact instance just do:
trial.TrialContacts.Add(contact);
context.SaveChanges();
EF will take care of the intermediate table insert for you. Note that adding Contacts and Trials works the same as if they weren't related.

There's a trick that was not obvious to me when setting this up. TableA must be added to TableB, not just to itself. In fact, looking at the generated entities each entity has a List<> of the other entity.
class TableA
{
List<TableB> TableB;
}
class TableB
{
List<TableA> TableA;
}
For example, if I want to add a TrialContact to a ClinicalTrial then I write:
context.ClinicalTrials.TrialContacts.Add(trialContact);
context.SaveChanges()
Then the xRef table be updated to reflect the relationship.

Related

SQL LINQ query keeps looping through two tables

I am trying to call a linq query in asp.net 5. However, my query results in an infinite loop of data between two tables.
Logs (logs_historical)
meterID (FK)
log_data
-----
Meters
meter_uid (PK)
My goal is to have multiple logs related to one meter.
Relationships
Foreign key Base Table = logs
Foreign key Column = meterID
Primary Base Table = meters
Primary Key Colum = meterID
This is my linq query
records = dbContext.logs.Where(e =>(e.timestamp.Value.Month == inputDate.Month)).ToList() ;
1) This screenshot shows the table information and (foreign key table)
When I look into the foreign key table information, it also has the logs.
Going into the logs will show the same table from picture (1)
2)
I'm sure this was asked before, but I do not know what this problem is called. I am new to databases. Thanks for any advice!
As a quick fix, you can probably use dbContext.Configuration.LazyLoadingEnabled = false;
just before your query. You can disable it globally as well.
What happens is Entity Framework will eagerly load all related entities. If you have entities that go several levels deep, or that reference each other, well, as you have experienced, it will continue to follow those relationships. Disabling lazy loading will prevent this. Please note that you will have to explicitly declare anything you want included via the .include() function.
The other option is to redesign your database so that this isn't the case, but sometimes that just isn't feasible. I don't really know the intricate workings of your project, so I am speculating here.
EDIT:
I forgot to add, if you go into the model browser and explore the models that were created for you by Entity Framework, you will find those relationships that are causing the issue. If you are using code first, you can easily fix this. If you are using database first, you are somewhat at the mercy of how EF interprets relationships.

Code first of EF, how to define navigation property relationship without setting foreign key between table in database

I use code first of Entity framework. There are two classes "Question" and "User". I defined a relationship as below:
this.HasRequired(v => v.Creator).WithMany(v => v.Questiones)
.HasForeignKey(v => v.CreatorId).WillCascadeOnDelete(false);
After gernerating the database I found that it always create foreign key between Id of User and CreatorId of Question. Because of lower performance of FK(and other reason),I want to define navigation property relationship without setting foreign key in database? Delete FK after EF created it?
If cannot do this using fluent api, could you tell me why EF designed in this way please?
About the lower performance of FK. I have a User table with 5 Million records in it. when I insert a Question into db, since the db check the question.CreatorId validation from User table, it always slower than without FK.
And there are many other reasons that I need to remove FK.
I think I am somewhat obsession because I think that deleting FK after created it is strangely and ugly. What i want is implementing this by using something like WithoutForeignKey in fluent api:
this.HasRequired(v => v.Creator).WithMany(v => v.Questiones)
.WithoutForeignKey(v => v.CreatorId).WillCascadeOnDelete(false);
Without questioning why are you trying to do this strange thing and going just to the answer: you could delete fk constraint after generated, or you could use migrations and remove FK generation from the migration code.
SQL code generated when traversing nav properties will work even if fk constraint doesn't exist, except for cascade deleting
If you want a relationship between two tables, you need to define a foreign key. No way around it. Even if you use Map() in fluent api, you can only hide the foreign key in your model, in the background EF will still use it and it will exist in the database.
Also I don't get what you mean by "performance" of foreign key? One extra (likely small) column won't make a difference. If you mean the navigation properties for the performance part, you can do 3 things:
Don't include them in your model
Make them non-virtual to disable lazy loading
Disable lazy loading all together with ctx.Configuration.LazyLoadingEnabled = false;
If you don't want to tell db about relation and treat both entities as not related (I wonder why), then just ignore these navigation properties and FK field. Note that you will be responsible for managing related entities: saving and loading them from db, updating ids etc
this.Ignore(q => q.Creator);
this.Ignore(q => q.CreatorId);
And you also need to ignore other side of relation, otherwise EF will generate FK column with default name Creator_CreatorId. So in Creator entity configuration:
this.Ignore(c => c.Questiones);

Many-to-Many relationship in WPF with EF and SQLite

I'm following this tutorial in order to implement a local database (using SQLite) for my WPF application.
Everything works as it should, although I have a logical problem I don't know how to solve using this approach. I'll simplify it below.
Database-wise, I have 2 tables (A,B) which share a many-to-many relationship, and thus require a JOIN table as well (ABJoin).
In my actual code however, I'd like to use only 2 models: A and B, which each having a list of the other type. Like this:
public class A {
// ...fields
List<B> bList;
}
public class B {
// ...fields
List<A> aList;
}
How can it be implemented in EF+SQLite?
Searching online, I have found some solutions, but nothing that applies to SQLite, so I was not sure how they'd work.
Configure Many-to-Many Relationships in Code-First
If you are using many to many join table then your each class should have a list of the join table.
It cannot work the way you are thinking.
Are you sure that it is a good idea not to have a third entity?
Lets say your two entities were DepartmentStore and Product, a typical example for an n:n relationship. A department store can sell many products and a product may be available in many departments stores. This results in a third entity which connects the two above, in the example above this would something like ProductAvailability.
If you think about it more careful, then you might realize that the new connecting entity might have properties of its own. In my example this might be NumberOfProducts, will states the available quantity of a product in a certain department store.
In my experience, it is quite common for the connecting entity to have a real value that goes beyond just connecting two other entities.
I also took a look at you example which it about Album and Artist entities.
Do you want to make a data model where an Album can be created by more than one Artist?
Entity Framework doesn't have automatic many-to-many mapping.
Instead of this, you can map A and B to intermediate table as one-to-many.
If you are not obliged to use only EF, I suggest to try NHibernate ORM instead.
It has convenient many-to-many mapping and generally more powerful.

Adding column to many-to-many auto generated table

I have Class and Student objects. Both have collection of another as property. Which automatically creates many to many table. Is there a way to add column to this table which relates to the relationship without creating many-to-many table by myself ?
No, there isn't. You have to promote the association table to an entity and have a one to many association to in on both Class and Student.
Yes it is possible, although really #Ricardo is technically correct really you should promote the join table to a fully qualified entity.
Some blogs posts that I have seen where people add extra properties to a many-to-many join table can be found here:-
http://thesoftwaresimpleton.blogspot.co.uk/2010/03/nhibernate-many-to-many-with-extra.html
http://nhforge.org/blogs/nhibernate/archive/2010/12/26/many-to-many-relationships-with-properties.aspx
http://www.thebuttonfactory.nl/?p=874
Google search turns up a lot (espically S.O. questions)

Fluent nHibernate Join

I have an entity that maps to a table called Rule. The table for this entity has an FK to another Table called Category. I'm trying to figure out how to pull in a property from Category in my Rule entity. I'm pretty sure I want to use a join in my entity mapping, but I can't figure out how to configure it so that it works. Here is my mapping:
Join("Category", x =>
{
x.Map(i => i.CategoryName, "Name");
x.KeyColumn("CategoryId");
x.Inverse();
});
Here is the SQL that it's generating...
SELECT ...
FROM Rule rules0_ left outer join Category rules0_1_ on rules0_.Id=rules0_1_.CategoryId
WHERE ...
Here is the SQL that I want.
SELECT ...
FROM Rule rules0_ left outer join Category rules0_1_ on rules0_.CategoryId=rules0_1_.Id
WHERE ...
I can't seem to find anything on the JoinPart that will let me do this. Subselect looks promising from the little bit of documentation I've found, but I can't find any examples of how to use it. Any advice on this problem would be much appreciated. Thanks!
"Join" is poorly named. a "join" in an NHibernate mapping implies a zero-to-one relationship based on a relation of the primary keys of the two tables. You would use a join if, for instance, you had a User table and a UserAdditionalInfo table, with zero or one record per User. The UserAdditionalInfo table would likely reference the PK from User as both a foreign key and its own primary key. This type of thing is common when a DBA has to religiously maintain a schema for a legacy app, but a newer app needs new fields for the same conceptual record.
What you actually need in your situation is a References relationship, where a record has a foreign key relationship to zero or one other records. You'd set it up fluently like so:
References(x=>Category)
.Column("CategoryId")
.Inverse()
.Cascade.None();
The problem with this is that Category must now be mapped; it is a separate entity which is now related to yours. Your options are to live with this model, to "flatten" it by making the entity reference private, changing the mapping to access the entity as such, and coding "pass-throughs" to the properties you want public, or by using a code tool like AutoMapper to project this deep domain model into a flat DTO at runtime for general use. They all have pros and cons.

Categories

Resources