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
Related
I have an object in C#
class Products {
public int ProductId {get; private set;}
public string DisplayName { get; set; }
public int DisplayOrder { get; set; }
public List<ProductImages> Images {get; set;}
}
class ProductImages{
public string Channel { get; set; }
public string ImageType { get; set; }
public byte[] Image {get; set;}
}
Now there is already a procedure for GetProducts which returns everything but the images, otherwise I would probably turn the entire query into an XML object and do serialization, though I have been asked not to.
The decision is:
Create a new column in this query and only that column is XML (or JSON) and then just deserialize the array of ProductImages
Make a separate call to the database to get the child object. That is pass in Product Id and return a table of ProductImages and on the server side loop through the table and create child objects.
Does the cost of deserializing an object out weight the cost of hitting the database connection again and looping through a table of records?
I think the first solution is better. Usually it's better to avoid hitting the database repeatedly.
In any case it's easy to set up a small test, and measure time and memory use for both options, and select which one fits better
This decision should be driven by the model design considerations, rather than implementation considerations.
If all of the following is true, use a single BLOB for all images in the Product table:
Images are never shared among products - this may be useful when multiple versions of the same product exist, but they look the same, e.g. different model years of the same product,
Images are never updated individually - this includes situations when you add new images, remove old images, replace images with new ones, etc.
Never need a subset of product images - this may be desirable when you show different images of the same product in different markets, e.g. products labeled in different languages
Otherwise, make a separate table attached to Product in many-to-one relationship for non-shared images or with an additional many-to-many table for shared images.
In some cases it may be beneficial to remove Images from Product, and opt for adding an API similar to GetProductImages(productId, additionalCriteria) instead, with additionalCriteria representing the context in which you want to use images (e.g. the market).
Finally, you may want to opt for lazy loading of images in situations when some use cases do not show images at all - for example, drop-down lists may include just the DisplayName, while a more detailed view may include images. This consideration applies to both normalized and denormalized (all images in a BLOB) solutions.
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.
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)
I have a method called GetCustomer that returns a Customer object.
Customer object is as below.
Public class Customer
{
public int Id { get; set;}
public string Name { get; set;}
public int CompanyId { get; set;}
}
Lets say Customer is related to a Company and I have to display this customer information on the screen UI. Now, when I call the GetCustomer method I only get back the details about the Customer. On the screen, I also need to display the companyname that this customer belongs to.
One easy way to do this would be to have a property called CompanyName in the customer object and fill it from your datalayer method. But I'm not sure if thats best practice. If the customer also belongs to a department, now I need to have DepartmentId and DeptName as properties. Ids are a must since sometimes I need to send the Id to get the full Dept/Company object.
I don't want to have the full objects for Department and Company in the Customer object.
I assume this is a common scenario where a particular object is linked to others using an ID and when you bring back the main object, you just need to display the name from the other linked objects.
What is the best to way to handle this. My main intention is to avoid an (or more) extra database call.
I'm NOT using Linq or Entity Framework, just regular ADO.NET.
This situation depends on your goals as;
1 - if you want to avoid extra DB calls, you have to code your UI via your db communicator with only one instance, open it only once and flush its members (adapter, command ..etc.) every time after making DB calls and close connection at the end of data transfers.
2 - for other purpose of your question, use lazy loading. put only id's on your entity and initialize and use the id's belonging entity if needed!
For example:
public class Customer
{
public int Id { get; set;}
public string Name { get; set;}
public int CompanyId { get; set;}
}
public class Company
{
public int CompanyId;
//company fields
}
// .. on your business layer if you need to use Company data:
// examine your Customer instance as "customer"
Company userCompany = GetCompanyWithId(customer.CompanyId);
but as you no doubt of your guess, data that is going to load is depends of your needs. Think simple. If your only need is Department and Company names, than you can create a view on your DB and can call it on your code. You can create an entity as CustomerWithFullData and you can put a Customer and a Department etc. in this entity and when you need to show full data you can fill this with DB View. Or dont bother to create entities. If you dont need entity, Call DB View directly DataSet and bind Tables. So you can transfer data collection work to DB and this is what we want to do.
As i said before, think simple.
What I would do is to retain an OO structure at the level of your business objects, and modify your DAL to return all the information you need with a single DB round-trip.
For example, you could have a stored procedure that returns two result sets: one for the Customers, and another for the Companies they reference. You could use table valued parameters to pass the SP a list of one or more Customers to look-up.
Depending on the size of your DB and your performance requirements, you also might be able to read the entire Customer and Company tables into memory when the app starts, cache the results, and manage insert/update/deletes against that data.
As a way to learn NHibernate, I came up with a small project that includes a typical users & groups authentication system. It got me thinking about how this would be done. I quickly put together the following classes and mapped them to the database, which worked after a lot of trial and error. I ended up with a three-table database schema with a many to many association table between the User and Group tables.
public class User
{
public virtual string Username { get; set; }
public virtual byte[] PasswordHash { get; set; }
public virtual IList<Group> Groups { get; set; }
}
public class Group
{
public virtual string Name { get; set; }
public virtual IList<User> Users { get; set; }
}
My question is regarding the scaleability and potential performance of this sort of class design. If this was in a production system with tens of thousands of users, even with lazy-loading on a Group's Users collection, any call to the Groups property could set off a potentially HUGE data retrieval.
How would NHibernate cope with such a scenario and how might I improve upon my design?
Don't create these as properties. Add functions to these classes which will allow you to fine tune your queries (through the use of parameters) to retrieve the specific data sets you require.
I know this question is old, but just happened to stumble upon it. You state "even with lazy-loading on a Group's Users collection, any call to the Groups property could set off a potentially HUGE data retrieval." Why? Presumably the number of groups is not tens of thousands, and accessing the Groups property on User would only load the Groups collection, not the Users collection within the Groups collection (unless Users wasn't marked to lazy-load). The huge data retrieval would only occur if you accessed the Users collection in Group, in which case I would recommend not having that relationship accessible from the Group mapping.