Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

November 2011 - Posts

Inline Image in ASP.NET

Update February 2nd 2013: you can use tag mapping to have all your controls render inline images.

Inline images is a technique that, instead of referring to an external URL, includes all of the image’s content in the HTML itself, in the form of a Base64-encoded string.

It avoids a second browser request, at the cost of making the HTML page slightly heavier and not using cache.

Not all browsers support it, but current versions of IE, Firefox and Chrome do.

In order to use inline images, you must write the img element’s src attribute like this:

   1: <img src="data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub/
   2: /ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcpp
   3: V0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7" 
   4: width="16" height="14" alt="embedded folder icon"/>

The syntax is: data:[<mediatype>][;base64],<data>

I developed a simple control that allows you to use inline images in your ASP.NET pages. Here it is:

   1: public class InnerImage: Image
   2: {
   3:     protected override void OnInit(EventArgs e)
   4:     {
   5:         String imagePath = this.Context.Server.MapPath(this.ImageUrl);
   6:         String extension = Path.GetExtension(imagePath).Substring(1);
   7:         Byte[] imageData = File.ReadAllBytes(imagePath);
   8:  
   9:         this.ImageUrl = String.Format("data:image/{0};base64,{1}", extension, Convert.ToBase64String(imageData));
  10:  
  11:         base.OnInit(e);
  12:     }
  13: }
Simple, don’t you think? Winking smile
Checking if an Unloaded Collection Contains Elements with NHibernate

If you want to know if an unloaded collection in an entity contains elements, or count them, without actually loading them, you need to use a custom query; that is because the Count property (if the collection is not mapped with lazy=”extra”) and the LINQ Count() and Any() methods force the whole collection to be loaded.

You can use something like these two methods, one for checking if there are any values, the other for actually counting them:

   1: public static Boolean Exists(this ISession session, IEnumerable collection)
   2: {
   3:     if (collection is IPersistentCollection)
   4:     {
   5:         IPersistentCollection col = collection as IPersistentCollection;
   6:  
   7:         if (col.WasInitialized == false)
   8:         {
   9:                 String[] roleParts = col.Role.Split('.');
  10:                 String ownerTypeName = String.Join(".", roleParts, 0, roleParts.Length - 1);
  11:                 String ownerCollectionName = roleParts.Last();
  12:                 String hql = "select 1 from " + ownerTypeName + " it where it.id = :id and exists elements(it." + ownerCollectionName + ")";
  13:                 Boolean exists = session.CreateQuery(hql).SetParameter("id", col.Key).List().Count == 1;
  14:  
  15:                 return (exists);
  16:         }
  17:     }
  18:  
  19:     return ((collection as IEnumerable).OfType<Object>().Any());
  20: }
  21:  
  22: public static Int64 Count(this ISession session, IEnumerable collection)
  23: {
  24:     if (collection is IPersistentCollection)
  25:     {
  26:         IPersistentCollection col = collection as IPersistentCollection;
  27:  
  28:         if (col.WasInitialized == false)
  29:         {
  30:             String[] roleParts = col.Role.Split('.');
  31:             String ownerTypeName = String.Join(".", roleParts, 0, roleParts.Length - 1);
  32:             String ownerCollectionName = roleParts.Last();
  33:             String hql = "select count(elements(it." + ownerCollectionName + ")) from " + ownerTypeName + " it where it.id = :id";
  34:             Int64 count = session.CreateQuery(hql).SetParameter("id", col.Key).UniqueResult<Int64>();
  35:  
  36:             return (count);
  37:         }
  38:     }
  39:  
  40:     return ((collection as IEnumerable).OfType<Object>().Count());
  41: }

Here’s how:

   1: MyEntity entity = session.Load(100);
   2:  
   3: if (session.Exists(entity.SomeCollection))
   4: {
   5:     Int32 count = session.Count(entity.SomeCollection);
   6:     //...
   7: }
NHibernate Pitfalls: Querying a Collection Count

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

Beware when querying a one-to-many collection (bag, set, map, list, etc) with the LINQ standard operators Any() or Count() (or even with the collection’s own Count property: if the collection is mapped as lazy = true, it will be loaded entirely from the DB (if it is not already loaded). That is because the Any() and Count() methods are from LINQ to Objects, not LINQ to NHibernate:

   1: Int32 ordersByProduct = product.OrderDetails.Count();    //causes loading of all order details

There are two possible solutions:

  • Map the collection with lazy = extra and use the collection's Count property;
   1: mapper.Class<Product>(ca =>
   2: {
   3:     //...
   4:     ca.Set(x => x.OrderDetails, x =>
   5:     {
   6:         x.Key(c => c.Column("`PRODUCTID`"));
   7:         x.Inverse(true);
   8:         x.Lazy(CollectionLazy.Extra);
   9:         //...
  10:     }, c => c.OneToMany());
  11: }
  • Perform an independent query (not on the collection) to find if the association has any elements:
   1: var existOrderForProduct = session.Query<OrderDetail>().Where(x => x.Product.Id == 100).Any();
More Posts