Microsoft Entity Framework link table issue - c#

I was hoping someone could give me a bit of advice here. I am wondering if I am on track or way off base in my approach. I am using Entity Framework, database first approach. I have a link table that associates people to each other. Person 1 associated to Person 2 as a friend for example. (association_type holds a key value associated to a lookup table)
I noticed that Entity Framework creates two separate navigation properties.
[EdmRelationshipNavigationPropertyAttribute("IntelDBModel", "FK_a_Person_Person_t_Person", "a_Person_Person")]
public EntityCollection<a_Person_Person> a_Person_Person
[EdmRelationshipNavigationPropertyAttribute("IntelDBModel", "FK_a_Person_Person_t_Person1", "a_Person_Person")]
public EntityCollection<a_Person_Person> a_Person_Person1
In other parts of the application, I have successfully used Entity Framework to write data to the database. For example, I have a person to telephone relationship.
In the person to telephone scenario, I create a t_Person (p) object, then create a t_Telephone (t) object and use p.t_Telephone.Add(t);
That seems to work fine.
I am somewhat lost in terms of how to manage this person to person link table insert.
When saving to the database, I use foreach to iterate through the People objects.
foreach (t_Person p in People)
{ctx.t_Person.AddObject(p);
...
}
I know what person is associated to what person in this People object collection. However, I don't know how to utilize the t_Person navigation properties (a_Person_Person) to save the person1 and person2 values to the link table (a_Person_Person).
Any hints would be greatly appreciated.

I think the given situation will generally give you hard time when using EF, since you are linking two foreign key two one table with same Primary key, since the relationship or lazy loading would be difficult to handle you might get double records or wrong records, I would add another property to the t_person table like datecreated which would make the the EF treat t_person table as not an association, but as actual entity giving you more control over entity and insertion and deletion.

Related

Entity Framework 6 big query in inheritance

I have an inheritance strategy Table per Type (TPT) with an abstract class "Task" with a lot of concrete classes (like 30 classes).
When I try to show a worklist of "to do tasks", so asking EF for the abstract class, or when I try to get a generic task by ID, EF makes a 10000 lines query joining every concrete class, that result very slow.
There is a way to configure EF to avoid the big query?
In the worklist method, I need only fields of the abstract class.
This is my code:
public Task GetTaskById(int id) {
return this.repository.Tasks.Where(t => t.ID == id).FirstOrDefault();
}
public IQueryable<Task> GetWorklist() {
return this.repository.Tasks.Where(t => a.ActivitySate.Code == ActivitySateEnum.TO_DO);
}
Thank you
Relational databases don't handle the concept of inheritance very well. Several strategies have been invented for entity framework to mock inheritance.
Which strategy suits you most depends on which kind of queries and updates you perform most often.
Suppose you have a class Person, and two specific kinds of Persons: Teachers and Students. There are two popular strategies to implement inheritance
Table per Type (TPT)
Every class is represented in a separate table. In our example three tables are created: a Persons table, a Teachers table with a foreign key to the Person it is, and a Students table with a foreign key to the Person data of the Student.
If you query: "give me the Persons that ...", only one table needs to be inspected. However, if you ask: "give me the Students who ...", then a join between the Persons table and the Students table is needed.
If you add / update / remove one Student, then two tables need to be updated.
If in future one column needs to be added to one of the classes, only one table is involved.
Adding a new kind of Person, like Sponsors is easy, however they have to be Persons and inherit all Person columns. If later you decide that a Sponsor is not a Person anymore you are in trouble.
This method is most suitable if you ask far more often for Persons than for Students and Teachers. It is less suitable if you ask quite often for Students with Person data. Also if you add / remove / update Students very often, don't use this method.
Also use this method if you need to create a Person that is neither a Teacher nor a Student yet, but later may become one of them, or maybe both Teacher and Student
Table per concreate class (TPC)
There is no separate table for Persons. All Person properties are in the Teachers table as well as in the Students table.
Querying "Students who ..." or "Teachers that ..." will only involve one table. However querying "Persons that ..." will involve the concatenation of data retrieved from the Students table with data retrieved from the Teachers table.
Add / Remove / Update a Student will always involve one table.
Adding a column to a Student involves changing one table. However adding a column to Person involves changing both Students and Teachers tables.
Adding a new kind of Person, say Janitors or Sponsors is easy. It won't be a problem if in future a Sponsor is not a Person anymore.
You can't create a Person, it always has to be either a Teacher or a Student. A Student never can become a Teacher, he will become a new Person (which seems a bit ironic :-). No Student can be a Teacher as well.
Use this method if you seldom ask for Persons who ..., but most often ask for Students who ...
Conclusion
The strategy to choose for your inheritance depends on how you will use your tables.
You seem to have 30 kinds of Persons implemented as TPC (no separate Persons table). If you ask for Persons who ..., your database has to concatenate the results from all 30 tables.
If you think this is by far the most used kind of query, consider changing the inheritance strategy to TPT. Whether you should do this depends on whether the database is already filled with a lot of data or not. If you are using code-first, you'll probably start with a fairly empty database.
The problem is that you use a ba repository that does not return IQueryable, so it doesn ot allow EF to actually use the filters you DO have (you do, right?) where you limit the returned data to only some fields.
So, what is lett is materialize the entity (which is SOOOO standard for the repository antipattern). And there you go.... for that.... It NEEDS to join TPT. Those are 30 classes, which mean 30+ tables. First, the query likely has no 10k lines. Second, this is normal and smallish for really complex SQL (which you DO have here). Third, you set that up yourself - yes, this is what is needed to pull in all the data.
Solution? Get rid of the suplus repository (DbContext IS a repository, you know) and then make the filter based on the base type and make sure to project ONLY the needed fields into an anonymous class, so EF CAN do optimization.

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.

Entity Framework 6 specific column mapping

In SQL, I would tell the database what the foreign key constraint is.
But fluent EF6 apparently does not have a way for me to specify what column to use when binding collections.
Is it not possible to tell DbModelBuilder exactly what column to bind relationships on? Or does it demand to be the primary key at all times?
Table_Person
id int // pkey. Multiple people records
UniqueID int // the unique person
sometext varchar(256) // database therefore tracks changes to this, since unique person can have many records (pkeys).
Table_Address
id int //pkey
fk_unique int // should map to UniqueID of person, NOT the pkey.
line1 varchar(512)
state varchar(64)
etc
One unique person has many records, and their uniqueID (not pkey) has many associated addresses. Actual structure is far more complex than that. But am looking for a way to do this fundamentally...
Would very much so like to have an ICollection<Address> Addresses within the Persons model. But to enable such a thing for code-first migrations... seems impossible?
Yes I could Add-Migration and then modify the generated code/sql manually. But doesn't that defeat the point? Or is that common practice?
If you're able to modify the DB schema you could put UniqueIDs for people into their own table named "Person" and rename the existing table to "PersonVersion". Then have FKs to the new "Person" table on "PersonVersion" and "Address". And finally, create the Person, PersonVersion, and Address models in your app code and EF should bind without problem.

Entity Framework Code First reference a common database

I have a common database that multiple applications use, and one of the tables in that common database is a Person table.
I know I can't have foreign key relationships cross database.
However, I was hoping I could still do something like
public Programmer
{
public virtual Common.Models.Person Person { get; set; }
}
(Programmer is a table in a different database than the person table)
Now, that wants to create a foreign key to a different database, which it can't, so it wants to recreate the tables in the database with the Programmer table.
I don't want that to happen, I just want to be able to do Programmer.Person and it grab the person model from the common database.
Since you can't use FKs which is what makes this possible, is there a way around this? Or what is the best practice to deal with a common database like this?
Thank you.

Entity Framework 4 and SQL Server 2008 Multiple Possible Foreign Keys

I am trying to come up with a database design that would work with Entity Framework 4 Code First. Actually, I have no experience yet of EF4 Code First but as I understand it, if I write the code, it will create the database and tables.
The issue is this. There are various types of auctions, they all have some common fields and some specific ones. In the code I envisage having a base abstract class called Auction and subclasses like LowestUniqueBidAuction and EnglishForwardAuction etc.
Nothing surprising there. The problem is that I imagine the database structure to mimic this. I imagine an Auction table and a LowestUniqueBidAuction table and a EnglishForwardAuction table. In the Auction table I imagine a foreign key into one of these two tables for each row depending on the type of auction that that row is. I also imagine another column in the Auction table with the name of the derived auction table (such as EnglishForwardAuction).
The problem is that whenever I've ever created a foreign key I've had to specify the name of the foreign table into which the key points (which makes sense). In this case, however, there is one of many tables that the key could point. So there are many issues here. Firstly, I could simply not use a foreign key and just use an ordinary field, but then the database will not be able to maintain data consistency for me. The second issue is how will EF Code First handle this? In other words, how will it know that if I ask for all EnglishForwardAuction rows from the Auction table that it should look at the column with the table name and then join on the EnglishForwardAuction table to get the extra fields?
Has anyone ever faced similar issues?
Thanks,
Sachin
This problem is solvable in Entity Framework in a number of ways - read up on how EF handles inheritance and what strategies are available.
There are basically three strategies how to handle this:
(1) Table per Hierarchy
You have only one single table, that represents all possible sub classes. Of course, this means, several rows (that only exist in a given subclass) must be nullable, since they don't show up / don't exist in super classes or other subclasses.
(2) Table per Type
Each subclass gets its own table, and by default, the sub-types table shares the PK with the base classes' table - e.g. PK = 1 in Auction will also be PK = 1 in EnglishForwardAuction. So your subclass tables reference the base table - not the other way around.
(3) Table per Concrete Type
Each concrete subclass (your separate auction types) gets its own table, but that table contains everything - all the columns, from that specific type, but also its base type.
Read more here:
Inheritance in the Entity Framework
Inheritance and Associations with Entity Framework Part 1
Entity Framework Modeling: Table Per Hierarchy Inheritance
Entity Framework Modeling: Table Per Type Inheritance
Searching for Entity Framework Inheritance and/or one of these strategies will reveal a lot more hits, too - that topic is very well covered and discussed on the interwebs! :-)

Categories

Resources