An advice to Microsoft toolchain users. Embrace what they churn out these past years. ASP.NET MVC, Entity Framework, Code-first EF(i.e. model-centric coding, not to be confused with designer), jQuery(not made by Microsoft, but now has a blessing from them). They deliver nice technologies way very late, it's a disservice to your skillset if you will not quickly learn these enabling technologies. Microsoft is already late, don't let yourself be late with Microsoft's latest technology.
MVC
MonoRail 2003 vs ASP.NET MVC 2007
ORM
NHibernate 2004 (Hibernate 2001) vs Entity Framework 2008
See? how long before Microsoft "legitimizes" certain technologies to the eyes of many Microsoft tools-using devs. And what's the year now? 2011. Hiding in the cave?
Use 21st-century techniques Don't lag behind, leave ASP.NET use ASP.NET MVC, leave ADO.NET use ORM and don't use sp-centric programming, not everyone are going gaga over sp, look at your Java counterpart devs, their DBA trusted them on touching the base tables, binding the ORM directly to tables, could it be that Java devs are DBA-grade application developers? and as such are more amenable and trusted on using ORM, hmm.. :-)
Start embracing the five pillars of maintainable software: ORM, the MVC pattern, unit testing, mocking, IoC.
"Simplicity can't be bought later, it must be earned from the start" -- DB
Sunday, July 10, 2011
Saturday, July 2, 2011
WCF error. The underlying connection was closed: The connection was closed unexpectedly.
To trace the root of cause of that generic error more easily, put this in your WCF's web.config
Then double-click the traces.svclog in C:\_Misc folder
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData= "c:\_Misc\traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
Then double-click the traces.svclog in C:\_Misc folder
Thursday, June 30, 2011
NHibernate foreign key property, solution on model binding impedance mismatch.
There's a little problem with NHibernate if you strictly adhere to its proper domain modelling. You will end up with a class like this (note Line 6):
If some components could allow direct binding to ProductX, there won't be too much problem with clean entity modeling of NHibernate. You can not use the ProductX directly as a DataPropertyName of your DataGridView for example.
There's a solution on that though, we can take a page from Entity Framework. EF forces one to use primitive types on model's foreign keys instead of stating the fact that it is a pointer to other records; for example, this is how your EF model looks like:
See the ProductID there? It is model-binding-ready. However, if you just quick-glance that class, it is not immediately obvious that an entity(ProductId) has a relationship with other entity; for all we know, ProductId could just be a barcode misrepresented as integer type. And notice that reaching the ProductId's other properties(say Category, or StockLevel) is not readily available from that property alone. Fear not however, as we all know that the first thing you shun after using ORM is joining tables; with an ORM, you don't need to join the classes to reach the foreign key's other properties(fields, e.g. Category, StockLevel); when you have a foreign key attribute or necessary mapping for foreign key on a model, EF automatically populates its corresponding object. Like this example:
That's how we will also tackle NHibernate model-binding-mismatch. But with a twist, we will do it in reverse instead, we will introduce primitive types, so we can directly bind them to UI widgets. An example implementation:
That's very clean compared to EF's approach, NH's approach directly mimics the problem domain as we still use the ProductX as a pointer to Product entity; UI-concerns-wise, we just need to introduce a new property on our model whenever we need something for the widgets to bind upon.
However, there's a problem with NHibernate populating those properties at the same time. It cannot bind a field to two properties. So for that, we have to do this:
After you get the records from NHibernate:
Before you save the records via NHibernate:
But that easily gets old, we need to make a helper to automatically re-hydrate those properties.
This is our NHibernate assigner helper, it's very short and concise:
And this is the Lookup attribute:
To use on opening:
To use on saving:
public class SalesDetail
{
public virtual SalesHeader SalesHeader { get; set; }
public virtual int SalesDetailId { get; set; } // Primary Key
public virtual Product ProductX { get; set; }
public virtual int Qty { get; set; }
public virtual decimal UnitPrice { get; set; }
public virtual decimal Amount { get; set; }
public virtual byte[] Version { get; set; }
}
If some components could allow direct binding to ProductX, there won't be too much problem with clean entity modeling of NHibernate. You can not use the ProductX directly as a DataPropertyName of your DataGridView for example.
There's a solution on that though, we can take a page from Entity Framework. EF forces one to use primitive types on model's foreign keys instead of stating the fact that it is a pointer to other records; for example, this is how your EF model looks like:
public class SalesDetail
{
public SalesHeader SalesHeader { get; set; }
public int SalesDetailId { get; set; }
public int ProductId { get; set; }
public int Qty { get; set; }
public decimal UnitPrice { get; set; }
public decimal Amount { get; set; }
public byte[] Version { get; set; }
}
See the ProductID there? It is model-binding-ready. However, if you just quick-glance that class, it is not immediately obvious that an entity(ProductId) has a relationship with other entity; for all we know, ProductId could just be a barcode misrepresented as integer type. And notice that reaching the ProductId's other properties(say Category, or StockLevel) is not readily available from that property alone. Fear not however, as we all know that the first thing you shun after using ORM is joining tables; with an ORM, you don't need to join the classes to reach the foreign key's other properties(fields, e.g. Category, StockLevel); when you have a foreign key attribute or necessary mapping for foreign key on a model, EF automatically populates its corresponding object. Like this example:
public class SalesDetail
{
public SalesHeader SalesHeader { get; set; }
public int SalesDetailId { get; set; }
public int ProductId { get; set; }
public int Qty { get; set; }
public decimal UnitPrice { get; set; }
public decimal Amount { get; set; }
public byte[] Version { get; set; }
[ForeignKey("ProductId")]
public virtual Product ProductX { get; set; }
}
That's how we will also tackle NHibernate model-binding-mismatch. But with a twist, we will do it in reverse instead, we will introduce primitive types, so we can directly bind them to UI widgets. An example implementation:
public class SalesDetail
{
public virtual SalesHeader SalesHeader { get; set; }
public virtual int SalesDetailId { get; set; }
public virtual Product ProductX { get; set; }
public virtual int Qty { get; set; }
public virtual decimal UnitPrice { get; set; }
public virtual decimal Amount { get; set; }
public virtual byte[] Version { get; set; }
[Lookup("ProductId")]
public virtual int? lookup_ProductX { get; set; }
}
That's very clean compared to EF's approach, NH's approach directly mimics the problem domain as we still use the ProductX as a pointer to Product entity; UI-concerns-wise, we just need to introduce a new property on our model whenever we need something for the widgets to bind upon.
However, there's a problem with NHibernate populating those properties at the same time. It cannot bind a field to two properties. So for that, we have to do this:
After you get the records from NHibernate:
foreach (SalesDetail d in sh.Sales)
{
d.lookup_ProductX.Value = d.ProductX.ProductId;
}
Before you save the records via NHibernate:
foreach (SalesDetail d in sh.Sales)
{
d.ProductX = s.Load<Product>(d.lookup_ProductX.Value);
}
But that easily gets old, we need to make a helper to automatically re-hydrate those properties.
This is our NHibernate assigner helper, it's very short and concise:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Reflection;
using System.Collections;
namespace NhLookupAssigner
{
public static class Helper
{
public static void SetupModel(this ISession s, object model)
{
Type modelType = model.GetType();
foreach (PropertyInfo p in modelType.GetProperties())
{
LookupAttribute a = p.GetCustomAttributes(false).OfType<LookupAttribute>().SingleOrDefault();
if (a != null)
{
string lookupName = p.Name.Substring(p.Name.IndexOf('_') + 1);
PropertyInfo targetProperty = modelType.GetProperty(lookupName);
Type targetPropertyType = targetProperty.PropertyType;
// get property's(public virtual Product Product { get; set; }) object
object nhValue = modelType.InvokeMember(lookupName, BindingFlags.GetProperty, null, model, new object[] { });
// get property's object's primary key
object pkValue = nhValue.GetType().InvokeMember(a.PrimaryKey, BindingFlags.GetProperty, null, nhValue, new object[] { });
// set property(e.g. public virtual int? lookup_Product { get; set; }) value
modelType.InvokeMember(p.Name, BindingFlags.SetProperty, null, model, new object[] { pkValue });
}
else
{
if (p.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(p.PropertyType))
{
object list = modelType.InvokeMember(p.Name, BindingFlags.GetProperty, null, model, new object[] { });
foreach (var x in (IEnumerable)list)
{
s.SetupModel(x);
}
}//if
}
}//foreach
}//void SetupModel
public static void SetupNh(this ISession s, object model)
{
Type modelType = model.GetType();
foreach (PropertyInfo p in modelType.GetProperties())
{
LookupAttribute a = p.GetCustomAttributes(false).OfType<LookupAttribute>().SingleOrDefault();
if (a != null)
{
string lookupName = p.Name.Substring(p.Name.IndexOf('_') + 1);
PropertyInfo targetProperty = modelType.GetProperty(lookupName);
Type targetPropertyType = targetProperty.PropertyType;
object inputValue = modelType.InvokeMember(p.Name, BindingFlags.GetProperty, null, model, new object[] { });
object nhValue = s.Load(targetPropertyType, inputValue);
modelType.InvokeMember(lookupName, BindingFlags.SetProperty, null, model, new object[] { nhValue });
}
else
{
if (p.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(p.PropertyType))
{
object list = modelType.InvokeMember(p.Name, BindingFlags.GetProperty, null, model, new object[] { });
foreach (var x in (IEnumerable)list)
{
s.SetupNh(x);
}
}//if
}
}//foreach
}//void SetupNh
}//class Helper
}//namespace NhLookupAssigner
And this is the Lookup attribute:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NhLookupAssigner
{
[AttributeUsage(AttributeTargets.Property)]
public class LookupAttribute : Attribute
{
public string PrimaryKey { get; set; }
public LookupAttribute(string primaryKey)
{
this.PrimaryKey = primaryKey;
}
}
}
To use on opening:
void DoOpen()
{
using (var s = Mapper.GetSessionFactory().OpenSession())
{
var z = s.Query<SalesHeader>().Where(x => x.SalesHeaderId == int.Parse(uxRecordIdentifier.Text)).Single()
s.SetupModel(z);
bdsHeader.DataSource = z;
}
}
To use on saving:
void DoSave()
{
using (var s = Mapper.GetSessionFactory().OpenSession())
using (var tx = s.BeginTransaction())
{
var sh = (SalesHeader)bdsHeader.Current;
s.SetupNh(sh);
s.SaveOrUpdate(sh);
tx.Commit();
}
}
Tuesday, June 28, 2011
When to use dynamic vs pure reflection?
First of all, a reflection on reflection. Reflection is not a black magic, to know it you don't need to face the mirror and summon some dark forces, but somehow this a bit advance programming is making some feel proud and boasting to peers if they grok reflection, thinking others don't. There's nothing rocket science about reflection. Reflection function names and property names are very intuitive on .NET, you will hardly need documentation. What one need is a due diligence and a bit of googling-fu and asking questions on stackoverflow if one cannot easily infer the right method and property names.
Now back to regular programming. Given this, using pure reflection:
And this, using C# 4's dynamic capability:
Which one would you use? I would choose the second code on two conditions, if I'm sure on certain terms that the environment to deploy on will allow to install .NET 4 runtime, and also sure that the certain property (e.g. ID) always exists; the pure reflection is very tedious to code. Make a third condition for choosing the second code, if there's .NET 5 already, no one will sneer at the .NET 4-specific code, second code will have the illusion of backward-compatibility if .NET 5 is out already :p
Some look at latest-version-specific code with disdain ;-)
And oh, it won't hurt to embed the if statement on array's extension method:
Now back to regular programming. Given this, using pure reflection:
// List all properties of a model
foreach (PropertyInfo p in modelSourceType.GetProperties())
{
// If the property is collection, list all the ID of each collection's item
if (p.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(p.PropertyType))
{
object list = modelSourceType.InvokeMember(p.Name, BindingFlags.GetProperty, null, modelSource, new object[] { });
foreach (var x in (IEnumerable)list)
{
object objValue = x.GetType().InvokeMember("ID", BindingFlags.GetProperty, null, x, new object[] { });
System.Windows.Forms.MessageBox.Show(objValue.ToString());
}
}//if
}
And this, using C# 4's dynamic capability:
// List all properties of a model
foreach (PropertyInfo p in modelSourceType.GetProperties())
{
// If the property is collection, list all the ID of each collection's item
if (p.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(p.PropertyType))
{
dynamic list = modelSourceType.InvokeMember(p.Name, BindingFlags.GetProperty, null, modelSource, new object[] { });
foreach (var x in list)
{
System.Windows.Forms.MessageBox.Show(x.ID.ToString());
}
}//if
}
Which one would you use? I would choose the second code on two conditions, if I'm sure on certain terms that the environment to deploy on will allow to install .NET 4 runtime, and also sure that the certain property (e.g. ID) always exists; the pure reflection is very tedious to code. Make a third condition for choosing the second code, if there's .NET 5 already, no one will sneer at the .NET 4-specific code, second code will have the illusion of backward-compatibility if .NET 5 is out already :p
Some look at latest-version-specific code with disdain ;-)
And oh, it won't hurt to embed the if statement on array's extension method:
foreach( PropertyInfo p in
modelSourceType.GetProperties().Where( x => x.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(x.PropertyType)) )
{
dynamic list = modelSourceType.InvokeMember(p.Name, BindingFlags.GetProperty, null, modelSource, new object[] { });
foreach (var x in list)
{
System.Windows.Forms.MessageBox.Show(x.ID.ToString());
}
}
Saturday, June 25, 2011
My site's style, how-to
Someone asked how I accomplish the styling on my blog. Without further ado, head to Alex Gorbatchev's syntax highlighter
Since I'm using the <pre /> method, I have to HTML-encode my code before I post it in my blog, for that I created the following ASP.NET MVC utility:
Note the use of ValidateInput(false), if you don't put that attribute, ASP.NET MVC will be in paranoid mode, anytime it encounters tags from user input, it will refuse to continue doing anything to prevent cross-site scripting.
And this will be your code in view:
I wrote that code(using WebForm tags) prior to Razor support in ASP.NET MVC, and that's the only currently supported in ASP.NET MVC on Mono, I'm on Mac OS X now.
For console-like output, example:
I'm using the following css style:
And to use full-screen content on blogger, disable the content-outer class in your blog's content, the easiest way to do it is to change the <div class='content-outer'> to <div class='x_content-outer'>
Lastly, if you don't want to include the namespace when copying code or you just want to paste the only relevant code to your blog(good also for pasting code to stackoverflow), use block highlighting, if you are in Visual Studio, hold Alt then start highlighting the indented code of your class; on MonoDevelop on Mac, hold the command button, unfortunately this doesn't work well, it can only highlight up to the last column only, and unfortunately, most of the last line of the code you are copying is a single character only, i.e. the curly bracket }
Since I'm using the <pre /> method, I have to HTML-encode my code before I post it in my blog, for that I created the following ASP.NET MVC utility:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace HtmlEncoder.Controllers
{
[ValidateInput(false)]
public class HomeController : Controller
{
public ActionResult Index(string Encode = "")
{
ViewData["Encode"] = Encode;
return View();
}
}
}
Note the use of ValidateInput(false), if you don't put that attribute, ASP.NET MVC will be in paranoid mode, anytime it encounters tags from user input, it will refuse to continue doing anything to prevent cross-site scripting.
And this will be your code in view:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<% using(var c = Html.BeginForm()) { %>
Paste your code here:
<p><%: Html.TextArea("Encode", new { cols = 120, rows = 12 }) %></p>
<p><input type="submit" value="Encode"/></p>
Copy the following HTML-encoded code:
<% string s = Html.Encode(Request["Encode"]); %>
<p><%: Html.TextArea("Output", s, new { cols = 120, rows = 12 } ) %></p>
<% } %>
I wrote that code(using WebForm tags) prior to Razor support in ASP.NET MVC, and that's the only currently supported in ASP.NET MVC on Mono, I'm on Mac OS X now.
For console-like output, example:
Example
I'm using the following css style:
<style type='text/css'>
.console {
background-color: black;
color: #00FF00;
font-family: courier;
}</style>
And to use full-screen content on blogger, disable the content-outer class in your blog's content, the easiest way to do it is to change the <div class='content-outer'> to <div class='x_content-outer'>
Lastly, if you don't want to include the namespace when copying code or you just want to paste the only relevant code to your blog(good also for pasting code to stackoverflow), use block highlighting, if you are in Visual Studio, hold Alt then start highlighting the indented code of your class; on MonoDevelop on Mac, hold the command button, unfortunately this doesn't work well, it can only highlight up to the last column only, and unfortunately, most of the last line of the code you are copying is a single character only, i.e. the curly bracket }
Subscribe to:
Posts (Atom)