How to load navigation data in Entity framework Code first? - c#

I have the following situation:
http://www.mediafire.com/view/?brjyqlj4rvjako9
When you read the picture in your browser you can see I have a three tables. The middle one is junction table.
All works well except the field Room in middle table (Bookings table) that always has a NULL value:
http://www.mediafire.com/view/?axz7ljskgcpl8cp
So, I saw that it needs to be loaded by hand before I make a reading operation on it.
How is this done in Entity Framework Code First as my project is running on it?
The relationship is many to many between guest and Room, Booking is a junction table.
Thank you

Is the property virtual?:-
public class Booking
{
...
public int RoomId { get; set; }
public virtual Room Room { get; set; } // Needs to be virtual
...
}
Navigation properties need to be virtual in order to enable lazy-loading.
If that's not the problem then I'll need you to post the source for your three entities (Room, Guest, Booking)

Related

What is the point of these virtual tables?

If I import a schema using entity framework, my tables get some virtual ICollection tables added to them if they have foreign key links on other tables. E.g.:
Table1
Id | ColumnA
Table2
Id | Table1Id_fk | ColumnZ
where Table1 will import as this model:
public class Table1
{
public Table1()
{
Table2s = new HashSet<Table2>();
}
public int Id { get; set; }
public string ColumnA { get; set; }
public virtual ICollection<Table2> Table2s { get; set; } // added because of the fk on Table2
}
This also then comes through if I serialise my objects as a string response so I can see an empty Table2s : [] in there, I'm wondering if it has something to do with that, but my main questions is
Why does this happen? What's the point? I can remove them and it doesn't stop working, so far it's just cluttering my code because I don't know what they're for :/
It's basically convenience provided to you by Entity Framework. This way in your code you can treat foreign key relationships as simple properties without having to do the join yourself.
If you remove these virtual properties, you'll have to connect the entities yourself.
Getting all Table2 items related to Table1
with virtual property:
var allTable2s = table1Item.Table2s;
without:
var allTable2s = dbContext.Table2s.Where(t2 => t2.Table1Id == table1Item.Id);
You should also have a look at the Entity Framework documentation: Understanding Relationships.
I am not sure if you're using EF Core, and if it became the standard there when you're scaffolding your models.
But:
Sometimes you need virtual Collections, to reference another Entity, avoiding that EF re-creates that entity over and over.
Imagine you have a table with Cars.
Theres also a table with Vignettes.
Imagine one of your Car's properties is a Collection of Vignettes.
If you were to retrieve 2 Vignettes from your Vignette table and set them as the vignettes on your Car, EF by default will assume that the vignettes are new Entities, and will create them in the database for you. This can be, to put it in nice words ... undesirable.
Now, if you make your Collection virtual, this suddenly becomes a Navigation Property for EF. It tells EF,
"hey, I would only like the references for the vignettes on this
entity"
So when you queue the object from your EF context, EF will get all the info of the entity, and then go look for your referenced entities (the vignettes in this case) and stuff them into your Car entity.
It also enables EF's lazy loading mechanic for that Collection.

SqliteNetExtensions is it possible to ignore a specified child when calling InsertOrReplaceWithChildren()?

I'm building a mobile app in xamarin that has a lot of relationships between classes. For simplicity consider it to be a "University" app that has the classes: ExamPapers, Students, ExamAnswers.
The ExamPaper class would look like this
public class ExamPapers {
[ManyToMany(typeof(Student_ExamPaper))]
public List<Student> Students { get; set; }
[OneToMany]
public List<ExamAnswers> Files { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<ExamSection> Sections { get; set; }
public string ExamName { get; set; }
[PrimaryKey]
public string Id { get; set; }
}
So at the moment any sqlitenetextension operation (the ones that end with "WithChildren") will interact with all the relationships when I often just want to interact with one at a time. Here are some example scenarios:
A student "Lana" is just granted access to an ExamPaper "Mathematics 101". Now to grant her access I need to load; all other students with access, all the files for the exam, all the sections. Otherwise these relationships get deleted when I call "InsertOrReplaceWithChildren".
I want to find out the first question in an ExamPaper. I call "GetWithChildren(examId)". I now have an object with a lot of information I don't want (e.g. 300 students and 300 ExamAnswers).
Sorry if I missed something relevant in the documentation, but I've read it through a couple times now. https://bitbucket.org/twincoders/sqlite-net-extensions
Thanks.
Answer on your question in title: No. You cannot.
SQLite-Net-Extensions does not provide such flexible API for manipulating related data.
But there is one helpful thing that can be used in specific cases:
You can work with junction tables as simple tables through SQLite-Net methods (methods without *WithChildren postfix) if junction tables has PrimaryKey (Id).
For example if you have any data which you want to get withoud additional (related) data, just simply call Table</*class*/>() method on specific table with Where(/*your condition*/) clause for getting only data that you really need. Then you can save modified data through Update method.
Unfortunately, this thing will not work with relations update (for example, if you want to move one ExamAnswer from ExamPaper to another ExamPaper object) because all SQLite-Net-Extensions attributes inherited from Ignore SQLite-Net attribute which is ignoring in all SQLite-Net operations.
But there is another one workaround (a little hacky), you can specify second class without any SQLite-Net-Extensions attributes and that's provide you to CRUD any field in specific table.

Want to know about database design and best practice of table relationship

At first I want to give an example. Here I will use code first approach to make database tables and their relationship. Please look at the class below. (C#)
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
You’ll notice that I'm making the two navigation properties (Blog.Posts and Post.Blog) virtual. This enables the Lazy Loading feature of Entity Framework. Lazy Loading means that the contents of these properties will be automatically loaded from the database when you try to access them.
Now Here is my question.
I want to make a Database as like below. The table names will be:
tblCompany
tblSite // Site will be create under Company (A Company will have one or more Sites).
tblLine // Line will be create under Site (A Site will have one or more Lines).
tblMachine // Machine will be create under Line (A Line will have one or more Machines).
So I will create,
Company table and it will have a Company_Id.
.
Then I will create,
Site table and this table will have Site_Id and Company_Id for making relationship between Site Table and Company Table
.
After that when I create Line Table should I user both Company_Id
and Site_Id?
I know I can use only Site_Id and by query I can get the Site which Company belongs to. But what is the best practice? Should I use every Table's Id or I just use Previous Table's Id?
And also provide the class if anyone can.
No, you shouldn't have every table in a hierarchy having every ID from every table above it, because we can use joins to link the tables together in the entire hierarchy chain.
There may be a very limited number of situations where it's specifically advantageous to have a lower level table have the ID of one much further above it, embedded within it but it's typically a developer convenience, when they think "I can't be bothered joining these 27 tables together every time I want to know which machine belongs to which company. I'll just have a companyid in the machine table and I promise I'll keep it updated by some complicated mechanism"..
.. Don't do it.. when you sell a site to another company you have to remember to transfer all the machines to them too, not just by selling the site, but visiting every machine and updating its company ID, otherwise the hierarchy gets messed up
What's the alternative, if your front end app will be querying a million times a second which machines belong to which company, and you don't want the database to have to join 27 tables together, a million times a second, to find this out? Caching; a separate system where you maintain a transient list of machines and companies. Every time you sell something or make a transfer, you invalidate the cache when you update the part of the database hierarchy. Upon next query, the cache misses and shall be rebuilt with the new info. The database only occasionally has to join 27 tables
This is starting to head into an opinion piece, and hence heading out of scope of a SO question/answer, but if you come up against specific problems as you implement your system, feel free to post them up
Ps: don't prefix your tables with tbl; it's obvious what they are. The days of having to give everything a name that included the type of thing it was have thankfully long gone

Entity framework navigation properties naming convention

I have two tables named as Profile and ProfileHistory.
Each record in ProfileHistory has to belong to a profile in Profile table, so there is a foreign key relation between two tables. Besides, in ProfileHistory table, there is a column named as ManagerId which also relates to Profile table with foreign key relation.
Profile table structure
Id int primary key
....
....
ProfileHistory table structure
Id int primary key
ProfileId int foreign key to Profile table
ManagerId int foreign key to Profile table
....
My question is:
Since currently I only know this, I am creating my entity model from database.
Model and therefore entity classes are created with navigation properties in
ProfileHistory entity like following:
public virtual Profile Profile { get; set; }
public virtual Profile Profile1 { get; set; }
It is so confusing. Because it is not clear which navigation property for which relation.
Even it is worse if I have more relations between two tables. navigation property names are becoming Profile, Profile1, Profile2, etc.
I was expecting to have the name of the navigation properties related with its foreign key relations.
How can I make my navigation property names something that related to its foreign key relation, in my case "from Profile1 to ProfileManager" ?
Thank in advance for your kind helps.
Muharrem
You can always rename the properties in model diagram. The name can be found in Properties window when you click on a navigation property.
I haven't tested it, but you can map a property to a column using an attribute:
[Column(“BlogDescription", TypeName="ntext")]
public virtual Profile Profile { get; set; }
[Column("Profile1", TypeName="int")]
public virtual Profile ProfileManager { get; set; }
Change the type and the name of the column as it is in the database.
The way I usually solve this is to add properties through partial classes that better represent what I'm after. This way if I need to delete the entity from the diagram and re-add it, I don't lose any renamed columns from the model.
The downside to this is that you need to remember that you cannot use them in Queries because EF won't know how to translate it into a SQL query. But if you've already got your Profile object, it's a lot easier to access myProfile.Manager than myProfile.Profile1.
So, for example, if EF created this for you:
public partial class ProfileHistory
{
public virtual Profile Profile { get; set; }
public virtual Profile Profile1 { get; set; }
}
I would end up creating a partial class like this to re-map the columns:
public partial class ProfileHistory
{
public Profile Manager
{
get
{
return this.Profile1;
}
set
{
this.Profile1 = value;
}
}
}
I did face the same problem some time ago. Well, it is even bigger then just confusing names. If you have navigation properties to another table, like Profile, Profile1, Profile2, next you delete/edit the corresponding foreign keys you may end up having those mixed. And if you used EntitySQL to query data you'll end up having bugs because of incorrect data retrieved/wrong table join conditions...
What I did was changing the t4 template and modified the way properties are generated. When property code text is being written you have the information about association and foreign key related to it. Foreign key names are unique in database and I named those with following pattern
FK_[Table]_[Meaning]
...
FK_ProfileHistory_InitialProfile
FK_ProfileHistory_UpdatedProfile
Next, having this information, I named the properties with the [Meaning] part of the foreign key name.

Naming collision with EntityFramework

I am using EF to access a SQL DB. For the sake of this example Lets assume I have a Users Table, a User Comments Table (comments made by users) and a Liked comments table (comments a user marked like on them) when the Context is generated I get in the User.cs file the following ICollections:
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Comment> Comments1 { get; set; }
How can I know which is which? Why does EF not add the foreign key table name to the column?
I have several of these issues.
in the edmx designer, click on the navigation property ("Comments" or "Comments1") and press F4 to show it's properties. The properties panel will display the foreign key name which will give you enough info to identify which is which.

Categories

Resources