Fluent NHibernate: Lock row in a multiple user environment - c#

Lets assume this hierarchy.
public class A
{
public int Id { get; set; }
public IEnumerable<B> Children { get; set; }
}
public class B
{
public A Parent { get; set; }
public string Name { get; set; }
}
I've created a app in WinForms and for database communication I use Fluent NHibernate. Multiple users can use the app simultaneously, however when a user decides to work with a specific instance of A (or a specific row in the database), I want to make that row non-accesible for other users. And when the user is finished working with that specific row, I want to make it accesible again. Can this be accomplished?
The idea is that a user fetches A and then works with some or all of its Children (List of B). At that stage, A is locked so that no other user can work with the children of A. When the user is finished working A is released and accesible to other users.

Fluent NHibernate is about your mapping. There are several ways to do data access with NHibernate. You do not specify which you use, but either way, the same principles apply.
What you describe is pessimistic locking. The way to do it in NHibernate is described here. I think you'd want to use LockMode.UPGRADE_NOWAIT.
If B-s can only be accessed through A it would indeed be sufficient to lock A.

Related

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

Should i validate if related entity exists before insert?

class Customer
{
public int Id { get; set; }
}
class Sale
{
public int Id { get; set; }
public int CustomerId { get; set; }
}
class SaleService
{
public void NewSale(Sale sale)
{
//Should i validate if Customer exists by sale.CustomerId before call save?
saleRepository.InsertOrUpdate(sale);
}
}
I'm using Domain Driven Design and Entity Framework.
Should i validate if Customer exists by sale.CustomerId before call save?
I usually don't do that. Normally, these information comes from the client which was loaded before (it existed). However, there are cases that the CustomerId is missing at the time you update your db.
Due to concurrency when many users access the system at the same time. But this case should be solved selectively using optimistic concurrency control (version). We usually don't try to handle concurrency in all the cases as it's almost impossible to do so and doing that also has side effects like performance issues, complexity,... We focus only on some critical code in the system that would cause problems if there is a concurrency issue.
A client tries to hack the system by sending an inappropriate CustomerId. But this is another issue that should be checked based on authorization or something like that.
In most of the cases, I think a foreign key constraint in db is enough.

Entity Framework and Stored Procedures Mismatched Entities/Models

I'm really looking for advice here on best practices so I will explain the situation. We have a fairly large application built on top of POCO and EF 4 with a complicated database. While we have been happy with Entity Framework there are definite performance improvements to be made for example with the following scenario (quite simplified).
We have a table called News which has a collection of users that have added it to their favourites and a collection of ratings (1 - 5) by users for example:
public class News
{
public virtual int NewsId;
public virtual string Title;
.......etc....
public virtual ICollection<User> UserFavourites { get; set; }
public virtual ICollection<Rating> Ratings { get; set; }
}
We have written a stored procedure which returns news for a user and allows us to return whether it is a favourite and whether it has already been rated by the user we are requesting the data for and the current rating for News rather than use EF to build this data from the ICollections and we end up with an object like below.
public class NewsDataModel
{
public int NewsId;
public string Title;
.......etc....
public bool IsFavourite { get; set; }
public bool IsRated { get; set; }
public double Rating { get; set; }
}
The stored procedure is much faster and a single database hit rather than EF with Lazy Loading which could be multiple calls but the data returned by the sproc does not match the POCO class for news which is above.
We have been trying to workout the best way to move forward with this as we have a INewsRepository which can either return the entity framework related class or the custom DataModel class we are populating with a stored procedure and ADO.NET. This doesn't feel right and I would appreciate any advice or insight from others experience about the best way to handle these scenarios when you want a single object with data built from multiple tables which would be a lot faster with a sproc than an entity framework call with lazy loading enabled.
Many thanks for any help
There is nothing wrong with a new method on your repository returning instances of NewsDataModel - it is still in the scope of your INewsRepository because it is data class constructed from news information. Otherwise you will have repository for every data model you defined.

NHibernate and Large Collections

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.

Categories

Resources