NHibernate - Sorting Entities based on Property/Column + how to manage? - asp.net-mvc

I'm writting an ASP.NET MVC e-commerce app using NHibernate and I want the end-user to be able to control the ordering of Product Categories (not just have them appear alphebetically etc.).
Normally, I'd add an OrderIndex/Sort column (of type int) to the Category table, and property to the Category domain class. But the problem is in having to constantly manage this special OrderIndex/Sort column as Categories are sorted, added, and deleted. I'd rather hide it away and make it transparent so callers don't have to set the property directly.
Sure I could write my own code to manage all this, but wanted to know if NHibernate has anything built in that could help me, or if it could hook this property up automatically.
If not then I was thinking of creating an OrderedEntity base class (all domain objects derive from an Entity base), and create an IOrderedRepository base Repository as well. Something like this:
public class Entity
{
public virtual int Id { get; set; }
}
public class OrderedEntity : Entity
{
public virtual int OrderIndex { get; set; }
}
public class Category : OrderedEntity
{
}
public interface IRepository<T> where T : Entity
{
T FromId(int id);
void Save(T entity);
}
public interface IOrderedRepository<T> : IRepository<T> where T : OrderedEntity
{
void MoveUp(int places);
void MoveDown(int places);
}
Does this seem like a good approach? I don't want to reinvent an inferior wheel.

So far I know Hibernate has an annotation #OrderBy where you can specify the ordering when the collection is loaded. But Hibernate won't manage the position that for you when you add or remove element in the collection.
You can however easily do that yourself and provide methods addItem and removeItem on the parent entity, which will keep track of the position (or the methods MoveUp and MoveDown as you suggest).

Related

Should ViewModels have Count properties to simplify the View logic?

Which approach to ViewModels is better:
1. Just have an ICollection<T> in the ViewModel and access it's properties in views, which is pretty much what I'd do in ASP.NET Forms, like this:
public ICollection<Order> Orders {get; set;}
so that in the View I would do something like this
#if(Model.Orders.Count > 0){
or
2. Create a property for the Count of an ICollection so the View can simply reference that value directly.
public ICollection<Order> Orders { get; set; }
public int OrderCount { get { return Orders.Count ; } }
and then in the view
#if(Model.OrderCount > 0) {
or perhaps a boolean property HasOrders to further reduce the logic in the View?
Edit
I'm a bit surprised by the comments, I accept that this is subjective, but then so are questions about whether to use a string property for a date and everyone has to start learning somewhere.
Will I have numerous uses of the OrderCount property? The if and then a label to display the actual count. As such it will be used more frequently than say the customer email address yet I would be astonished if anyone suggested that
public string Email { get; set; }
was taking things too far.
To try to refocus the question a little; what I'm trying to determine is should the ViewModel provide simple properties for everything the view needs - so there is no need to reach down into the Model.Orders to access the Count. Should the View be kept pure and free from logic / 'programming'
3.) Don't use a Collection<T> on a viewmodel, it's probably overkill. Instead, use T[]. Why? Because you shouldn't need .Add, .Remove, and other overhead methods offered by ICollection for an IEnumerable property in a viewmodel. In the end, if you are just using it as a DTO to pass data from a controller to a view, an array is perfectly fine. Nothing will have to be added to or removed from the enumerable during transit to and from the controller. Arrays are generally faster and leaner than Lists and other IEnumerable implementations.
public Order[] Orders { get; set; }
Then, don't use .Count, use .Length. Having a separate property is usually overkill too IMO. Why? Because it just means you end up writing more code where you don't have to. Why add an OrdersCount property when you can just use Orders.Length?
#if (Model.Orders.Length > 0) {
If you are looking for something a little shorter, you can use the .Any() LINQ extension method (note you will have to have using System.Linq; when using this in a viewmodel class, but nothing extra should be needed to use it in a razor view):
#if (Model.Orders.Any()) { // returns true if Model.Orders.Length > 0
One possible exception to this guideline could be if Orders is not set, meaning it is null. In that case, your razor code above would throw a NullReferenceException. For this you could create a HasOrders property on the viewmodel to test against null and .Length. However a simpler solution could be to just initialize the property in a constructor:
public class MyViewModel
{
public MyViewModel()
{
Orders = new Order[0];
}
public Order[] Orders { get; set; }
}
Granted, with the above someone could still set the array to null, so it's your decision of whether to do this, or create a separate property to test against null, or just test against null in your razor code.
using System.Linq;
public class MyViewModel
{
public Order[] Orders { get; set; }
public bool HasOrders { get { return Orders != null && Orders.Any(); } }
}
...or...
#if (Model.Orders != null && Model.Orders.Any()) {
Any way you go, you end up with a little more code in either the consuming class or the consumed class. Use these factors to decide which approach means less code to write:
a.) Is it possible for the property to be null?
b.) How many collection properties are in the viewmodel?
c.) How many times do you have to test against either null or .Length in a razor view?

Creating history table using Entity Framework 4.1

I am working on asp.net MVC 3 application and I am using codeFirst approach. I am trying to create history table or user table, Where I want to keep track of what columns were modified by user. How can I do this using EF Code First.
Do I need to do it after DataContext.savechanges ?
Please suggest.
Thanks.
The DbContext has a method called Entry<T>:
var entity = context.Items.Find(id);
entity.Name = "foobar";
var entry = context.Entry<Item>(entity);
entry will be of type DbEntityEntry<T> and has the properties OriginalValues and CurrentValues.
You could probably write something that will generically inspect these properties to see what has changed and then automatically insert a new record into your history table.
Either that, or use database triggers.
I'm not sure if this is really the "appropiate" way to do it, but this is how its usually done in sql:
Create an extra property version of type int or something.
Because you probably do not want to loop every time, add another property IsLatestVersion of type bool
When an entity is saved, check if the entity already exists. If so, set the entity on IsLatestVersion = false.
Increment the version, and save the changes as new entity.
Sounds to me like you want an a filter that inherits from ActionFilterAttribute. In my case, this is the simplest example that I have. This is my model, notice that the attributes dictate the mapping to the database.
[Table("UserProfile")]
public class UserProfile
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
In my case, it was as simple as the following, although it was not historical:
public sealed class UsersContext : DbContext
{
public UsersContext() : base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
LazyInitializer.EnsureInitialized(ref _initializer, ref isInitialized, ref initializerLock);
}
public void CheckDatabase()
{
Database.SetInitializer<YourDBContextType>(null);
using (var context = new YourDBContextType())
{
if (!context.Database.Exists())
{
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
// Uses your connection string to build the following table.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
The end result is not only EF being code first, but also allows for your models for your views to use primitives derived from your complex entities. Now, if you have another, lets say historical, DBContext then I would recommend modifying either the text transformation file or creating a base class for your entities. Both ways allow for an easy generation of code that could insert into your table, then follow up with that entity, clone it into a historical model and save. All that being said, I am a fan of database first approaches with concentration on constraints, triggers, etc. instead of a framework.

EF 4.1 Codefirst: Instantiate complex navigation properties

imagine having a simple POCO for EF 4.1 Codefirst:
public class Product
{
// Native properties
[Key]
public Guid ID { get; set; }
// Navigation properties
public virtual Category Category { get; set; }
public virtual ICollection<Customer> Customers { get; set; }
public Product()
{
this.ID = Guid.NewGuid();
// Do I have to instantiate navigation properties in the constructor or not???
this.Category = new Category();
this.Customers = new List<Customer>();
}
}
What I couldn't figure out so far is if I should instantiate complex navigation properties in the POCO's constructor or not?
Seems like all my current code is working if I don't instantiate, but I'm concerned that my code might cause problems in the future.
Are there any rules, best practices or any side effects?
Thanks for your ideas and tips!
You don't need to instantiate Category. Category is single entity which either exists or not - Product is not responsible for its creation. You can need to instantiate Customers to empty list.
The reason why it works now is because your context will wrap entities with dynamic proxy which will handle instantiation of you Customers collection. Because of that other code can access the collection without receiving NullReferenceException. This can change if you create instance of Product in your code without using EF. In such case there will be no dynamic proxy and your collection will be null = you will have to instantiate it yourselves.

Does using Implicit / Explicit conversion operators violate Single Responsibility Pattern in favor of DRY?

I need to convert between these two classes, and want to maintain DRY but not violate the Single Responsibility Pattern...
public class Person
{
public string Name {get;set;}
public int ID {get;set;}
}
public class PersonEntity : TableServiceEntity
{
public string Name {get;set;}
public int ID {get;set;}
// Code to set PartitionKey
// Code to set RowKey
}
More Info
I have some Model objects in my ASP.NET MVC application. Since I'm working with Azure storage I see the need to convert to and from the ViewModel object and the AzureTableEntity quite often.
I've normally done this left-hand-right-hand assignment of variables in my controller.
Q1
Aside from implicit/explicit conversion, should this code be in the controller(x) or the datacontext(y)?
Person <--> View <--> Controller.ConverPersonHere(x?) <--> StorageContext.ConvertPersonHere(y?) <--> AzurePersonTableEntity
Q2
Should I do an implicit or explicit conversion?
Q3
What object should contain the conversion code?
Update
I'm also implementing WCF in this project and am not sure how this will affect your recommendation . Please also see this question.
Q1: The controller.
Q2: Convert manually or with the help of a mapping tool such as AutoMapper.
Q3: I would put the code for this in a converter or mapper class like the following. Note that IConverter is shared among all converters, and IPersonConverter just exists so your controllers and service locators can use it.
public interface IConverter<TModel, TViewModel>
{
TViewModel MapToView(TModel source);
}
public interface IPersonConverter : IConverter<PersonEntity, Person>
{
}
public class PersonConverter : IPersonConverter
{
#region IPersonConverter
public Person MapToView(PersonEntity source)
{
return new Person
{
ID = source.ID,
Name = source.Name
};
//or use an AutoMapper implementation
}
#endregion
}

How do I pass multiple objects to ViewPage in ASP.NET MVC?

I think I know the answer, but I would like to bounce around some ideas.
I would like to pass several (in this instance 2) somewhat different pieces of data to a View. My initial thought is simply to wrap-up the various objects into a containing object and pass them along that way. Then from the View, I'd have something like
var objContainer = ViewData.Model;
var thisObject = objContainer.ThisObject;
var thatObject = objContainer.ThatObject;
and these could be used independently in the Master Page and View Page.
Is that the "best" way?
I find it useful to create additional classes dedicated that are to be presented to the Views. I keep them in a separate namespace called 'Core.Presentation' to keep things organized. Here is an example:
namespace Core.Presentation
{
public class SearchPresentation
{
public IList<StateProvince> StateProvinces { get; set; }
public IList<Country> Countries { get; set; }
public IList<Gender> Genders { get; set; }
public IList<AgeRange> AgeRanges { get; set; }
}
}
Then I make sure that my View is a strongly typed view that uses the generic version of that presentation class:
public partial class Search : ViewPage<SearchPresentation>
That way in the View, I can use Intellisense and easily navigate through the items.
Yes, the class that you specify as the model can be composed of other classes. However, why not just use the dictionary like so:
ViewData["foo"] = myFoo;
ViewData["bar"] = myBar;
I think this is preferable to defining the model as a container for otherwise unrelated objects, which to me has a funny smell.
I've got the same dealie going on. Here's my solution (may not be the best practice, but it works for me).
I created a number of "Grouping" classes:
public class Duo<TFirst,TSecond> { /*...*/ }
public class Trio<TFirst,TSecond, TThird> { /*...*/ }
and a factory object to create them (to take advantage of type inference... some of the TFirsts and TSeconds and TThirds can be LONG)
public static class Group{
public static Duo<TFirst, TSecond> Duo(TFirst first, TSecond second) {
return new Duo<TFirst, TSecond>(first, second);
}
/*...*/
}
It gives me type safety and intellisense with a minimum of fuss. It just smells because you're grouping together classes that essentially have no real relation between them into a single object. I suppose it might be better to extend the ViewPage class to add a second and third ViewModel, but the way I did it takes lots less work.

Resources