I know how to do SQL query to add foreign keys, connect to DataBase and fetch data in C# and such. But after long hours searching on Google, I cannot find any features (or classes, methods, API etc.) in C# that has anything to do with Foreign Key.
Back when I was in Rails, if two tables has relationship I can easily access a child table through the parent table by Teacher[0].Classes.Last . But these methods seems to be missing in C#? Am I right?
I'm working with C#, SQLCE and WPF.
I have two tables that has one-to-one relationship. But all the data including the reference key are inserted manually (e.g. this row, insert a "1", that row insert a "5" etc.) and to find a rows in the child table corresponding to a parent table's ID, I just have to do an if statement in C#.
So basically a Foreign Key to me is just another int column. I don't get what the reference actually does or is it just a naming convention? Just so reader of the code sees a reference and recongnize there is a relation, but the foreign key doesn't actually do anything substantially?
Back when I was in Rails, if two tables has relationship I can easily access a child table through the parent table by Teacher[0].Classes.Last, But these methods seems to be missing in C#?
You can do something similar with Entity Framework and many other ORMs out there.
So basically a Foreign Key to me is just another int column. ... Just so reader of the code sees a reference and recongnize there is a relation, but the foreign key doesn't actually do anything substantially?
Correct - the value of the foriegn key loses significance once you leave the database. Instead what is normal is to have nested objects. For example, you can have a Customer object which can contain an Address object. The Address object may also carry around its foriegn key value, but generally you wouldn't use it in the C# code (unless you were doing something like a LINQ query with it) - you would use the foriegn key value once you got back to the database.
A foreign key represents a relationship between objects in your Domain model. It enforces integrity.
(In some databases, foreign keys can also speed up queries because the query optimiser is able to make use of this information)
Related
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.
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);
I am using EF 5 with migrations and code first. It all works rather nicely, but there are some issues/questions I would like to resolve.
Let's start with a simple example. Lets say I have a User table and a user type table. The user type table is an enum/lookup table in my app. So the user table has a UserTypeId column and a foreign key ref etc to UserType. In my poco, I have a property called UserType which has the enum type.
To add the initial values to the UserType table (or add/change values later) and to create the table in the initial migrator etc. I need a UserType table poco to represent the actual table in the database and to use in the map files. I mapped the UserType property in the User poco to UserTypeId in the UserType poco. So now I have a poco for code first/migrations/context mapping etc and I have an enum. Can't have the same name for both, so do I have a poco called UserType and something else for the enum or have the poco for UserType be UserTypeTable or something?
More importantly however, am I missing some key element in how code first works? I tried the example above, ran Add-Migration and it does not add the lookup table for the enum.
If I understood properly your questions and what you're confused about,
Enums support has nothing to do with lookup tables on the Db side.
Enums are simply allowing you to have properties in your classes that are Enum-s and that is translated into 'int'-s basically - so there is nothing much else in there.
For more info you might wanna look at this video from Julie Lerman on Enum-s support
hope this helps
In my experience the enum is more important to your code than the lookup class so give it the proper name. I would also keep the look up class isolated without any relationship to the User in my Model. If it trully is only for lookup, then you don't need it hanging off of your User. Your enum with a DescriptionAttribute can fulfill the lookup in your code.
UserTypeLookup might be a good name since that sounds like what you will be using it for. Then you can use that class to maintain the table.
Assuming you don't map the relationship between UserTypeLookup and User in ef code first, the only thing you should need to create in the DB manually is the foriegn key relationship between the UserType column in your User table and the PK from the UserTypeLookup table. UserTypeLookup can still be an entity and EF should still generate the DB table for it even if you don't setup any relationships for it.
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! :-)
Pardon the massive headline.
I'm in the situation of having to build an application on top of a database, that I cannot make any changes to. The database does not have any primary- or foreignkeys set.
I'm using linq-2-sql, and I'm interested in having some properties exposed on the entities generated from my dbml. For instance, in the hypothetical example of a one-to-many relationship between table education and student - where each student record has a reference to an education id, I'd like to be able to go:
var student = GetAStudentFromContextOrWhatever();
var studentsEducation = student.Education;
It is my experience, that this kind of property is automatically generated when I drag'n'drop tables with foreignkey relationships from the server explorer.
However as previously mentioned, in this case I do not have these foreign key relationships - rather I am adding the relationships manually in the dbml file, specifying parent and child class.
When I add these relationships, I expect the involved entities in the designer.cs of my context to get populated with properties of a kind like those described above.
This, however, does not happen.
What must I do for my dbml to create these properties for me - based on these manually mapped associations between entities/tables that, on a database level, do not have foreign key associations?
Cheers!
L2S is just that Linq-to-SQL. If it isn't in SQL it won't be generated. The expression trees behind L2S just can't understand what you are doing. The place for your association is in a partial class file which you will have create manually. Also it probably won't update or insert through the association.
I know this is a very old question, but I just ran into the same problem. In order for the relationship in the DBML designer to automatically create the association properties for you, you need to have primary keys on your objects. If you click the column name in the designer, you'll see that your PK field has PrimaryKey = false. Switch that to True and build; all should be well.
Patrick