Splitting Out a Table to Improve Performance - nhibernate

my user's table in the database is becoming increasingly larger (in terms of columns not rows) and as a consequence is slowing down various areas of my site. This is because it tries to grab every column from the user's table everytime it does a join against it.
I figured i would keep all the common fields in the user's table and then put the additional fields in seperate tables. For example, say i have the following tables in my database:
Users:
- UserID (PK, Identity)
- UserName
- Password
...
UsersActivity:
- UserID (PK, FK)
- LastActivityDate
- LastLoginDate
...
UsersPreferences:
- UserID (PK, FK)
- HtmlEmail
- HideEmail
...
With the following entities:
public class User {
public virtual int UserID { get; set; }
public virtual string UserName { get; set; }
public virtual string Password { get; set; }
public virtual UserActivity Activity { get; set; }
public virtual UserPreferences Preferences { get; set; }
}
public class UserActivity {
public virtual User User { get; set; }
public virtual DateTime LastActivityDate { get; set; }
public virtual DateTime LastLoginDate { get; set; }
}
public class UserPreferences {
public virtual User User { get; set; }
public virtual bool HtmlEmail { get; set; }
public virtual bool HideEmail { get; set; }
}
I was just wondering what is the best way to map this for optimum performance? I figured i could do a one-to-one mapping on the Activity and Performance properties in the User entity. However as far as i understand one-to-one mapping doesn't support lazy loading and this approach would end up being slower.
I also looked into component mapping and wasn't too sure whether i could map this into a seperate table (please correct me if it would be better to keep it in the same table) and whether components supported lazy loading.
Before i go about doing some heavy refactoring of my application i thought i would get the opinion of someone who might have done this. Really appreciate the help.
Thanks
Edit: I found that you could lazy load a one-to-one relationship as long as it is required/constrained. Which it is my case. Therefore i went ahead and carried out the instructions in the following article:
http://brunoreis.com/tech/fluent-nhibernate-hasone-how-implement-one-to-one-relationship/
The trouble now is that i get the error:
NHibernate.Id.IdentifierGenerationException: NHibernate.Id.IdentifierGenerationException: null id generated for: UserActivity.

In NHibernate 3.0 one-to-one relationship supports lazy loading.
And I think that it is better to use Component with combination of Lazy property. Then you will be able to leave all properties in one table and not load them all at once.

You should do some additional application profiling to determine why you're having a performance problem. It's unlikely that it's due to the number of columns in the select list. You probably have an N+1 select problem.
That said, there are many good reasons to use a lightweight object so you might want to look at implementing a DTO (data transfer object) for this.

Related

Confused about DTOs when reading and editing. How to desing DTO for filling the form in VUEjs app?

I am trying to develop an enterprise-level application. I have domain and application services. I have created my DTOs for multiple purposes separately. But confused about which way I should use them from the API viewpoint.
I have complex objects lets say,
public class Entity{
public int Id { get; set; }
public string Name { get; set; }
public int? ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
}
public class Manufacturer{
public int Id { get; set; }
public string Text { get; set; }
}
And I have corresponding DTOs designed with composition now. It was separated before.
public class EntityBaseDto{
public string Name { get; set; }
}
public class EntityReadDto : EntityBaseDto{
public string Manufacturer { get; set; }
}
public class EntityWriteDto : EntityBaseDto{
public int? ManufacturerId { get; set; }
}
Now the question is,
I have a table which is filled with List<EntityReadDto> which is clear. Before, EntityReadDto also had the ManufacturerDto as fully included with id and text. Whenever I require to edit one of the entries from the table I was able to load the dropdown selected items or list of tags etc with the ids attached to the Manufacturer objects within ReadDtos. Now it is not possible. Since I wanted to simplify the codes I just converted them to strings that are read-only. Now I have created another endpoint to get an editable version of the record when needed. Ex: EntityWriteDto will be used to fill the form when the edit is clicked on a specific item. The manipulation will be carried on that DTO and sent with the PUT type request to edit the record.
I am not sure if this approach is ok for these cases. What is the best practice for this? I have many objects related to the entities from other tables. Is it ok to make a call to get an editable version from the backend or need to have it right away in a VUEjs app?

MVC4 / EF5 / Auto Increment

I'm not sure how to exactly word my question which is probably why I cannot find an example of this anywhere. I'm playing around with MVC4 & EF5 (Web API too) but I'm not sure how to proceed with the Model as I've never really had to do much with them before. I'm doing something around the Periodic Tablet of Elements and I want to make it so that I have a list built for an element with it's electron configuration. However, I'd like to have it just auto number based on the input order. How can I tell EF to auto-increment a field? Basically like a primary key field without that limitation behind it. Here's what I have so far - I'm just not sure how to proceed:
public class Elements
{
public int ElementID { get; set; }
public string Name { get; set; }
public int AtomicNumber { get; set; }
public string Symbol { get; set; }
public virtual Categories Category { get; set; }
public virtual States State { get; set; }
public virtual Occurences Occurence { get; set; }
public virtual ICollection<Configurations> Configuration { get; set; }
}
public class Categories
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
public class States
{
public int StateID { get; set; }
public string StateName { get; set; }
}
public class Occurences
{
public int OccurenceID { get; set; }
public string OccurenceName { get; set; }
}
public class Configurations
{
public int ConfigurationID { get; set; }
public int Order { get; set; }
public int Value { get; set; }
}
Looking above what I'd like is for anytime a value is added to Configurations.Order the value starts at 1 and increases with each new 'row' but only for that specific ElementID.
Does that make sense? I was looking at using Data Annotations but I couldn't find anything that matched other than a Key Field but that'd make each Order a unique number - which I don't want. I feel like I'm not expressing this correctly because of all the stuff I've been looking at to figure it out, so here's a picture! yay!
This very well could be something that is better off from a programmatic standpoint. Even though this data changes once in a blue moon, I wanted to try and do it through EF if possible just so I know how.
Thanks a ton in advance. Also, if you see any other glaring errors, by all means let me know :) I rarely get to work with this side of web dev so I'm sure there's ways to do things better.
How can I tell EF to auto-increment a field?
You can't. Not even for a simple auto-incrementing primary key. Let alone for a field that should increment in relation to other values.
The HasDatabaseGeneratedOption mapping method is not a way to tell EF how to generate key values. It tells EF if and how the database generates values for properties, so EF knows how to respond to that.
So you either have to generate the order numbers in code, or let the database do it (by a trigger, or by mapping CUD actions on Configurations to stored procedures) and tell EF that the database computes the values by HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed) in the configuration of the Order property.

Fluent NHibernate - Map 2 Identical classes to same table

I've seen this (unanswered) question asked once before, but in a different context. I'm looking to have two domain objects map to the same table, WITHOUT a discriminator. The two classes are:
public class Category
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual ReadOnlyCategory ParentCategory { get; private set; }
}
and
public class ReadOnlyCategory
{
public virtual int Id { get; private set; }
public virtual string Name { get; private set; }
public virtual ReadOnlyCategory ParentCategory { get; private set; }
}
The main difference is that all public properties of ReadOnlyCategory are read-only. My idea here is that I want all users of this class to know that they should only mess with the category they are currently 'looking' at, and not any other categories in the hierarchy. (I've left off other properties regarding the subcategories.)
Clearly, in the database, Category and ReadOnlyCategory are the same thing, and NHibernate should treat them very similarly when persisting them. There are three problems wrapped into one here:
1) How do I do the mapping?
2) When instantiating the objects, how do I control whether I instantiate Category or ReadOnlyCategory?
3) When persisting the objects, will the mapping be smart enough, or do I need to use an extensibility point here?
Any pointers on how I can get this to happen?
(Or am I crazy?)
This looks like wrong object model design to me. I don't see a good reason to introduce a new class just for authorisation reasons (whether user allowed to modify a given category object?). You may as well use one class and throw for example InvalidOperationException if an end user is not supposed to modify a category.

Fluent Nhibernate many-to-many where table has multiple columns

I am trying to to map a many to many relationship using Fluent NHibernate.
I have a table User and a second table Organization. The association table is UserOrganization which contains the UserId and OrganizationId. The UserOrganization table also contains a few other fields (YearBegan, YearEnd).
How would I go ahead and map those using fluent mapping.
Thanks
You should probably make UserOrganization its own entity that contains those fields. That also gives you more flexibility in terms of cascading updates and deletes.
public class UserOrganization {
public virtual User User { get; set; }
public virtual Organization Organization { get; set; }
public virtual DateTime YearBegan { get; set; }
public virtual DateTime YearEnd { get; set; }
}

How to structure domain model when using NHibernate Search/Lucene

I am messing around with NHibernate Search and Lucene to create a searchable index of legal entities. My domain model looks somewhat like this:
[Indexed]
public abstract class LegalEntity : AggregateRoot
{
public virtual Address Address { get; set; }
}
public class Person : LegalEntity
{
public virtual string FirstNames { get; set; }
public virtual string LastName { get; set; }
}
public class Company: LegalEntity
{
public virtual string Name { get; set; }
}
public class Address : Component
{
public virtual string Street { get; set; }
public virtual string HouseNumber { get; set; }
// etc...
}
As the subclassing implies, LegalEntity is an NHibernate entity specialized as Person and Company, and Address is an NHibernate component.
Now, how would I best go about creating a really Google-like fuzzy search that includes all the fields of a LegalEntity, including those inside the Address component?
My first idea was to implement an AddressFieldBridge to help in bringing in the fields of the Address component, and then just throw in [Field] on all the fields, but then I could not find a way to construct a FuzzyQuery as a conjuntion between multiple search terms.
My next idea was to create an abstract property tagged with [Field] on LegalEntity, like so:
[Field(Index.Tokenized)]
public abstract string SearchableText { get; }
and then have Person and Company return texts that combine names and all the fields from the Address component into one string, which would then be tokenized and indexed by Lucene.
That, however, made me feel kind of icky.
I would like to learn the best and least intrusive (from a domain model perspective) way to accomplish this task - any suggestions are appreciated :)
Take a look at my question.
Andrey created patch to specify lucene stuff outside. Syntax ain't uber clean (maybe there's some progress done on this, haven't checked), but i guess it gets job done.