kenegozi.com

<form id='kenegozi' action='post'></form>

   
2008 May 12

Cloning a DetachedCriteria

tagged as: activerecord | nhibernate

I always need to look it up, so I might as well put it here for future reference:

 

What is a DetachedCriteria?

This is an ICriteria object, that is detached from any ISession, therefore is suitable to be passed around as a specification that is being built up dynamically.

 

Why would I want to clone it?

Well, say I want to run two similar queries (same WHERE part) but with a different projection or aggregation. For example - when fetching a paged collection, you'd want to create the spec criteria, then add Count projection on A to get the 'total number of records' ,and add the paging restrictions (sort, then from row 101 take 10 records). Now if you'd try to add the restrictions to the criteria to which you have already applied Count on, and error would occur.

 

 

Solution:

There's CriteriaTransformer class, which holds a few useful static methods, amongst them, Clone(DetachedCritetia):

DetachedCriteria spec = DetachedCriteria.For<Whadever>()
   ...; <= setup criterions

DetachedCriteria countCriteria = CriteriaTransformer.Clone(spec)
...; <= setup the count projection

DetachedCriteria pagedCriteria = CriteriaTransformer.Clone(spec)
...; <= setup the paging


ICollection<Whadever> stuff = whadeverRepository.FindAll(pagedCriteria);

int total = whadeverRepository.Count(countCriteria);
2008 May 9

Using nhibernate's named queries with ActiveRecord

tagged as: castle | activerecord | nhibernate | hql

One of the methods of querying the DB when using NHibernate, is to issue HQL queries. HQL stands for "Hibernate Query Language". It has a SQL-like syntax and is very intuitive for people with SQL background.

 

The way this works is that NHibernate 'compiles' the HQL query into SQL, and then issues the SQL query (using ADO.NET's facilities) to the DB.

 

Sounds pricey?

enter Named Queries.

now these are HQL (or SQL) queries, each has a name (obviously), that are been supplied to NH through the mapping. The queries are being translated and cached as IDbCommand objects as part of the framework initialisation, which mean that you get rid of the HQL->SQL overhead throughout the life of the process.

 

One other major benefit, is that the mechanism to actually execute these named queries, does not differentiate between HQL and SQL queries (for the simple fact that these queries have already been transferred to SQL at runtime). That gives you the possibility to replace HQL queries into tighter SQL queries (with the same parameters and which returns the same resultset) should your DBA figure out a better one.

 

But if you're using ActiveRecord, you usually do not have direct access into the mapping (.hbm) files. So how would you use named queries with AR?

 

enter HqlNamedQueryAttribute (not such a great name, as I did state that it would also work for SQL queries).

 

So, for an example, on this blog's source code, within PostRepository.cs you'd see this code:

...

 

#region queries
[assembly: HqlNamedQuery(Queries.FindPostsInArchive, Queries.FindPostsInArchive)]
[assembly: HqlNamedQuery(Queries.FindByUrlFriendlyTagName, Queries.FindByUrlFriendlyTagName)]
namespace KenEgozi.Com.Domain
{
    internal partial class Queries
    {
        internal const string FindPostsInArchive = @"
                from Post p
                where
                    year(p.Lifecycle.CreationDate) = :year and
                    month(p.Lifecycle.CreationDate) = :month
                order by p.Lifecycle.CreationDate desc";
        internal const string FindByUrlFriendlyTagName = @"
                select p
                from
                            Post p
                    join    p.Tags t
                where t.UrlFriendlyName like :urlFriendlyTagName
                order by p.Lifecycle.CreationDate desc;";
    }
}
#endregion

...

 

        public ICollection<Post> FindInArchive(int year, int month)
        {

            return session
                .GetNamedQuery(Queries.FindPostsInArchive)
                .SetParameter("year", year)
                .SetParameter("month", month)
                .List<Post>();
        }

...

Queries class is marked as partial, as other queries might be presented on other repositories or services that would need to add more named queries. I considered grouping of queries into groups by the using repository, or by aggregate roots, but the thing is - having all of the queries under the same namespace helps discoverability, and helps with preventing duplications

2008 Feb 28

Executing Plain ol' SQL in ActiveRecord Transaction

tagged as: castle | activerecord

I'm getting asked for this a lot (lately on the Castle's usergroup, and on many other occasions)

 

You friend is ActiveRecordMediator.Execute

 

So here is a sample:

ActiveRecordMediator.Execute(typeof(ActiveRecordBase), delegate (NHIbernate.ISession session, object data)
{
   IDbConnection con = session.Connection;
   IDbCommand cmd = con.CreateCommand();

 

// That's the key part - joining the current AR transaction scope
   session.Transaction.Enlist(cmd);  

 

// now you have a IDbCommand instance - use it at will


}, null);

If you want to create a proper method for handling the delegate instead of the anonymous one, then you can pass data in there (using the third argument) and it would get into the delegate as the "object data" thing.

2007 Nov 19

On Linq for SQL and POCO

tagged as: linq | activerecord | nhibernate

I'm looking at the option of using Linq To SQL for persistence.

 

Basic assumptions:

  1. Entities should be POCOs
  2. I like Linq as query language
  3. I hate visible generated code
  4. Would rather avoid xml configurations

Today I'm using NHibernate (so 1 and 3 are set), and AR Attributes (so 4 is set). As for querying, I resort to hql (nice, yet too stringy), ICriteria (still stringy) and NHQG (cool, super cool, yet coupled with NH, while Linq is a "query everything" language)

 

I tried Linq for SQL (on a VS C# 2008 Express Beta2). No designer. Hand coded the entity, and have used the attributes for mapping.

 

First problem encountered: in order to make a column lazy, I need to change the underlying type to Link<MyOriginalType>, and then I can tell the context (using a LoadingOptions) about whether to load the lazy properties.

 

Couldn't yet find a way to actually lazy load that property once the instance has already been loaded.

 

I much better like the way NH is handling things, with a runtime-generated proxy that takes care of lazy loading (among other stuff), so I get it without hassling my entities code.

 

Didn't even mention First and Second Level Caches.

 

I guess I'd have to try and hop into NHibernate.Linq, and try to help Ayende with bringing it forward. That would mean diving into NH code, something I haven't done for quite some time now ...

2007 Nov 18

ActiveRecord.Linq - naive but Working

tagged as: c# | linq | castle | activerecord | nhibernate

I've spent some times lately with Linq To SQL and have played a bit with the Mapping namespace.

Why I do not like it very much is a matter for a different post. The matter at hand is that I want the power of Linq, and I want the power of NHibernate, and I want the easy road of ActiveRecord.

 

What do I mean by that? I'd like:

  1. query language == Linq
  2. persistence engine == NHibernate
  3. Mapping == ActiveRecord attributes

the needed prequisites:

  1. Linq (framework => framework.Version >= 3.5)
  2. NHibernate.Linq (source => source.getFrom(Rhino-Tools) )
  3. Linq for ActiveRecord - Keep on Reading

So, Ayende has kick-started it, and with some help from Bobby Diaz, we have a prototype level NHibernate provider for Linq.

To make it work with ActiveRecord, all you need is to add:

using System;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
using NHibernate;
namespace NHibernate.Linq
{
public class ActiveRecordContext : NHibernateContext
    {
        public ActiveRecordContext() : base(null)
        {
            session = GetSession();
        } 
        private ISession GetSession()
        {
            ISessionScope scope = SessionScope.Current;
            if (scope == null)
                throw new InvalidOperationException("You should be in a SessionScope()");
            ISessionFactoryHolder holder = ActiveRecordMediator.GetSessionFactoryHolder();
            return holder.CreateSession(typeof(ActiveRecordBase));
        }
    }
}

and now you can do stuff like:

using (new SessionScope())
{
    ActiveRecordContext context = new ActiveRecordContext();
    var q =
            from c in context.Session.Linq<Category>()
            select c; 
    foreach (Category c in q)
        Console.WriteLine(c.Name);
}

Assuming Category has [ActiveRecord] mapping.

2007 Jul 6

Summing up the last two and a half years - Bye bye SQLink

tagged as: castle | activerecord | aspview | hql | personal

It was absolutely brilliant.

I started to work for SQLink on late December 2005 as a Team Leader in the Web Projects Department.

Colleaged by Oren Ellenbogen, it has been a pleasure. Our department head, Moti, was doing the best he can to create a very likeable working environment, and all our developers were enjoing a workplace that enabled them to learn a lot. Oren and I were directing all kinds of sessions with the developers, showing them stuff about .NET and the CLR, from "what are nullables", through "What does the 'using' reserved word mean", to "how the GC is actually working".

We have built this great website called GotFriends, that gave the company a great new source for recruiting new employees, and actually is ground breaking in the Israeli HR world. Building that site, we've used many technologies to make it work smoothly with the company's inner legacy HR system, and with the aid of the SQL master Moran Benisty, it even worked in an efficient way, and coded in a maintainable manner.

Mixing WebForms and Monorail, CodeSmith based BLL with ActiveRecord/NH, ASP.NET WebServices (asmx) and POX/JSON services, it was a very fun thing to work on, in addition to the business benefit to the company.

 

However, a few months ago the Web Project Department was closed, and the company started a new R&D team, leaded by Elad, the company's VP of Business Development. We were two developers (Moran and I), and we worked on several initiatives that the CEO Tamir, and Elad, were cooking all the time. Those projects were all Community-Driven-So-Called-Web-2.0-Kinda-Websites. It was a real delight, and I got the chance to learn a lot about the business side of running an Internet related initiative, as both Tamir and Elad are experienced and intelligent, and the process of refining ideas, with those two, was a real treat.

 

They also gave me the freedom to make all the technology decisions, and they've had enough faith in me to allow me run the projects using MonoRail and AspView, and running Castle ActiveRecord for DB access. Actually, most of the drive behind creating AspView was actually driven by Elad and Tamir, as I've promised to do the best I can to make sure that future additions to the team won't need to learn Boo / Velocity in addition to learn the Monorail MVC and hql.

 

Which actually worked great. Moran has left the team about two months ago, and we've brought three new guys along (Ili, Ofir and last but not least, Itay), and they have seam to easily get control of all the "funky" technologies I've put in use in our projects.

 

Sadly enough, one of the initiatives has stalled just before airing, due to some business decisions. Then we started a new one, and in about 3 weeks we've had a working proof-of-concept, and I really hope that the site will air during August. I give the credit to the team, and to the use of MonoRail/ActiveRecord, as it's such agile and suits highly-changing-environment, as most web initiatives are.

 

A point of interest: This very blog's engine was actually a beta testing for some of the stuff we were using on our last project.

 

That's it folks. I wish the SQLink family all the best, and I'm going to keep an eye on the cool stuff the R&D team is doing, and hopefully I'll report on their success (which would be an AspView success too ...) right here on my blog.

2007 Jun 24

Regionerate - c# region maker

tagged as: tools | castle | activerecord | monorail

Check out this nice tool from Omer Rauchwerger.

 

It could help a team to manage a coding convention. Should be very useful in Open Source environments. For example, when committing changes to castle project (or sending a patch) there is a coding standard than needs to be followed. Regionerate could help a lot with that effort.

 

I need to see if it can select methods and properties by attributes. It could then help making MonoRail controllers and ActiveRecord decorated classes more readable (region of all actions with a "SkipFilterAttribute", region of "Property" and region of "HasMany", etc.)

 

UPDATE:

Silly me, I forgot to mention that I found about this great tool at Roy Osherov's blog. A very good one, that is. Many Agile related stuff, and funny little things, too. So go on and subscribe to it's feed.

2007 Jun 20

Eagerly loading multiple collections in one roundtrip

tagged as: activerecord | nhibernate

Today at work I did a session with my team, showing them several methods to query the DB in a NH/AR enviroment.

When we talked about eager fetching, I said that doing it for more than one collection in one query isn't good (as advised in hibernate's site), since it might build up a rather large cartesian product.

Why? If we have a type Entity, that looks a bit like that:

class Entity
{
    ...
    [HasMany ...]
    public IList<Item> Items ...

    [HasMany ...]
    public IList<AnotherItem> AnotherItems ...
    ...
}

An eager fetch will do:

SELECT *
FROM
    Entities INNER JOIN
    Items ON Entities.Id = Items.EntityId INNER JOIN
    AnotherItems ON Entities.Id = AnotherItems.EntityId 

The result length will be e*i*a, where e is the number of rows in Entities table, i is the number of rows in Items table , and a .. (you fill the blank).

But, luckily for us, NH is keeping a single concrete copy of each entity in a session. Ayende is abusing that in a way, that makes the above possible, without the 3rd (or more) dimention in the cartesian product.

How it works? Using a MultiCriteria, he is getting his entities, eagerly fetching one collection at a time. So it would return e*i+e*a rows. So for the first query, NH will populate the Entity instances, with the first collection (Items) populated. For the second query, NH will populate *another* Entity instances with the second collection (AnotherItems) populated. But, since it's in the same session, actually the first Entity instances (with Items already populated) will get their AnotherItems collection populated.

That's why at the end of the snippet, you see that he actually deals with list[0]. That's where the first set of references is placed, and the other items in that list (list[1] ... list[n]) are just copies of the references to the same Entity objects.

Quite a similar approach was seen when Ayende has shown us how to eager fetch using SQL (at the end of the post). The query there returns an array of Message items and an array of User items, but the User instances actually are wired to their Message instances, so he is using only the first array.

2007 May 31

Castle build from the trunk - revision 3812

tagged as: castle | activerecord | monorail

From Castle Project users group:

 

 

I've just built the trunk yesterday (rev 3812).

Main reason: I needed the BaseControllerTest from Castle.MonoRail.TestSupport.


The build was targeting .NET 2.0, in release, and no tests were run.

You can download it from: http://www.kenegozi.com/Castle_r3812_net-2.0_release_not_tested.zip
Note that it is not tested, so use it at your own risk.
If you're not going production this week, it should not be a problem ...

2007 May 16

My blog is running on ActiveRecord-MonoRail-AspView

So long dasBlog. It was great to have you, but it's time to move on.

After a lot of work, I am proud to announce that my blog is running on MonoRail, using AspView for the views, and ActiveRecord to do DB stuff.

Not too fancy codewise, since I have very little spare time.

Most of the time spent on the blog upgrade process was on:

1. Exporting the data from the "old" blog, and

2. making a decent markup and design for the new one.

oh. and 3. letting WindowsLiveWriter do the edits, since I wasn't in the mood to create a backoffice.

I'll blog more about the process, and I'll make the source available.

Please leave your comments here about the overall look'n'feel. There must be tons of bugs and I want your feedback.

2007 Mar 19

ActiveWriter - 2nd preview is out

ActiveWriter is a VS2005 plugin, that adds a new item type for your projects. This item is actually a visual designer for ActiveRecord classes. Quite neat, and hopefully will increase the penetration of Castle's ActiveRecord to the "If there's no VS wizard, I do not use it" kinda guys.

You can read about it and download it from http://altinoren.com/activewriter/

2007 Feb 14

Long time no posting. Must write.

I haven't written much lately, since I was:

a. Learning for my final exam so I'd get my Bachelor's Degree at this decade.
b. Under a lot of preassure at work, since we have a cool web2.0 thingie approaching a public beta real soon (will be followed).
c. Sneasing my heart out, darn flew.
d. Got into a new project  at my personal business. This one is driven by Castle's ActiveRecord+MonoRail+AspView, and due to the client's request it'll use Access as the backend DB, and that would be a first-time-ActiveRecord/access for me. I still hope to convince him to at-least go for embedded FireBird.

So, stay tuned to some experiences with AspView, and hopefully in about a month you'll have two MonoRail/AspView driven websites out in the open. I am excited. Are you?

2007 Jan 4

NHibernate ' Could not find constructor for: ' in ' select new ' projection query

tagged as: castle | activerecord | nhibernate | hql

There are two facts here:
1. I love NHibernate.
2. I hate NHibernate's exception messages.

And here's my story.

On a project I'm working on, I need to show a projection of "top 10" from the database. let's show this on the good old Blog scenario: 

So I want to show the posts with the longest comments measured by the comment's length. Stupid, huh? but it's a demo only (I cannot expose the actual ERD). Let's say I want the top 5.

I am using Castle ActiveRecord. There is a Post and a Comment classes. However, I do not wish to load Posts objects, since It will load the Comments, too, and maybe other stuff that the Post class is related to. So I have defined a PostProjection class:

   1:  public class PostProjection
   2:  {
   3:      public string Title;
   4:      public int Length;
   5:      public PostProjection(string title, int length)
   6:      {
   7:          Title = title;
   8:          Length = length;
   9:      }
  10:  }

I have also added an [Import] attribute on the Post. The actual querying is done using the next hql :

   1:  public static PostProjection[] GetTopPosts(int postsToGet)
   2:  {
   3:      SimpleQuery<PostProjection> q =
   4:          new SimpleQuery<PostProjection>(typeof(Post), @"
   5:          select new PostProjection(p.Title, sum(c.LineCount)) 
   6:          from 
   7:              Post p inner join 
   8:              p.Comments c 
   9:          order by sum(o.LineCount) desc
  10:          group by p.Title");
  11:      q.SetQueryRange(postsToGet);
  12:      return q.Execute();
  13:  }

It worked great.

Yesterday I've upgraded my Castle dll's to the ones from build 229. It includes NHibernate 1.2.0.2002

Now the "select new" started to fail, and NHibernate started to claim than "Could not find constructor for: PostProjection".

I've been scratching my head, trying various approaches, and even was keen to skip the "new" and use an object[ ] and populate the Projection Array by hand, but then I tried changing the "length" parameter of the constructor from "int" to "long". Magically it solved the problem.

Now, if only NHibernate would have said :

Could not find constructor for: PostProjection.
Looking for: PostProjection(string, long)

I would've known what the problem was, and what should I change.

So what have we learned today?

1. NHibernate expects sum() to return "long" rather than "int"
2. NHibernate's error messages suck.

I've svn-ed the NHibernate trunk, added some code so this message would be more developer friendly, and I'm going to send the patch to NHibernate's JIRA.

2006 Dec 3

Things I've been doing lately

I've been off the radar lately, due to some extensive work I do on a website for my employer.

It is still in early stages and I cannot talk about the site itself, but I can talk a little about the technology that drives it.

In one word: Castle.

In a few more words:

Data Access and OR/m: Castle's ActiveRecord over NHibernate

Web UI Engine: Castle's MonoRail

ViewEngine: AspView (by yours truely, inspired by Ayende's Brail). All my spare time from work goes there.

Client Side Javascript stuff: Prototype and Scriptaculous.

I really believe in the efforts made by Castle group, and I hope the the site I'm working on will be successful, as to serve for yet another prove of concept.

 

One more thing I'm doing last month, is that I've decided to finally end the thing with my Bachelor's degree. I needed to retake Linear Algebra I (yep, that one the all the  non-bullet-time Matrixes ...   I H-A-T-E adjoined matrixes. yuck) so that's actually why AspView doesn't progress as I'd want it too (and as some of my readers want, too).

2006 Nov 5

Building Application using Castle RC2

Ayende has recently posted a walkthrough for building Web Apps using the Castle Project's libraries.

He covers ActiveRecord and MonoRail basics, showing off some of the shiny and new abilities (AR scaffolding, ARSmartDispatchers, Generics integration and so on).

The only thing missing is IoC-ing using Winsdor or even Binsdor. Maybe to hook some BL layer or something.

So it concludes (as of now) a Part I, Part II , and source-code.

If you wanna see a decent web development framework at action - tune up to those posts.

2006 Oct 26

MonoRail vs. WebForms

Ayende has posted about the matter, only he've used the title "MonoRail vs. ASP.NET" instead. I think that his title isn't accurate since MonoRail is actually a WebForms replacement that is built ontop of ASP.NET, exploiting all of the cool features found in ASP.NET and in the .NET framework alltogether. It's the Web development framework that Microsoft forgot. So it has the benefits of the Rails interpretaion for MVC, with the power of .NET.

Here is the comment I've posted to Ayende's post:

"My point of argue in favor of MR for people who are afraid of "non-microsoft" is, that actually MR is ASP.NET. It is just not WebForms.
You get all the good stuff from ASP.NET: the .NET framework for start, compiled views (on Brail - kudos to you), the HttpModule stuff, seeamless integration with AR.
This is what I say to the PMs, etc.
To the developers themselves who are afraid, There's a more detailed approach.
Developers (especially ones who didn't do web programming aside ASP.NET, and probably has a lot of VB experience but no PHP/JSP/ASP) like WebForms cuz they can get to the txtUsername.Text, txtPassword.Text, and txtAge.Text easily, not needing Request.Form["Password"] (hey - it's not typed !!!) . But then I reffer them to the fact that actually txtAge.Text isn't typed too. it's a string, and should be parsed, tried, validated etc.
They should also manually create a User instance, and fill it's properties.
Doing the same on MR with Dispatching and AR is there without any line of code. I show them an example aqnd then hold them as they almost fall off their chairs.
Not'n like a good example.
Maybe having a ViewEngine that's use c# or VB.NET instead of boo (not the WebForm ViewEngine which suck, but somthing similar to Brail) can make the move from WebForms to easier for developers, but frankly, as you've said, people who can't get it OJT with a few examples aren't the one's I'm likely to work with anyway."

2006 Oct 16

On Wheels and Squares

On a small debate with a friend, about weather he should design and implement a Data Access Layer himself, or use an existing framework, I came across a piece by Ayende about 25 Reasons Not To Write Your Own Object Relational Mapper.

I'd like to add a quote from Code Complete 2 about programmers who are reluctant to read (and use) existing solutions to known problems (on p. 823):

... even if you want to reinvent the wheel, you can't count on success. You might reinvent the square instead.

It's definitely not a Dave Barry kinda funny punch line, however it's very much to-the-point.

2006 Oct 15

Querying the DB using Castle ActiveRecord - NHibernate Query Generator

tagged as: linq | tools | castle | activerecord

There are many methods to query your data when you're on Castle's ActiveRecord.

Thanks to Ayende, we have a new cool way of doing that, namely NHibernate Query Generator 1.5.

1. You can skip querying, fetch everything and check it in the client:

   1:  Blog[] blogs = Blog.FindAll();
   2:  foreach (Blog blog in blogs)
   3:  {
   4:      if (blog.Name== "Cool Blog")
   5:      {
   6:          firstPostTitleName = blog.Posts[0];
   7:          break;
   8:      }
   9:  }

The Good: Type safety - can catch a lot of errors in compile time
The Bad:  One should let the DBMS handle queries. It's a total waste of resources.
The Bottom line: AVOID

2.  You can use direct SQL:

   1:  string firstPostTitleName = (string)ActiveRecordMediator.ExecuteQuery(
   2:      new ScalarQuery(typeof(string), QueryLanguage.Sql, @"
   3:      SELECT TOP 1 Title 
   4:      FROM Post INNER JOIN Blog ON Post.BlogId=Blog.Id
   5:      WHERE Blog.Name= ""Cool Blog"""));

The Good: Well, it'd probably work.
The Bad: Joins? Blog.Id? hey - I thought we are using an OR/M !! plus it's not type safe,
The Bottom line: AVOID AT AL COST

3. You can use HQL:

   1:  string firstPostTitleName = (string)ActiveRecordMediator.ExecuteQuery(
   2:      new ScalarQuery(typeof(string), @"
   3:      select title
   4:      from Post p
   5:      where p.Blog.Name = ""Cool Blog"""));
   6:   

The Good: Working with objects, nice and readable query string.
The Bad: not type safe,
The Bottom line: Use only when 4 and 5 are not applicable.

4. You can use ICriteria:

   1:  string firstPostTitleName = Post.FindOne(
   2:      Expression.Eq("Blog.Name", "Cool Blog"));

The Good: Working with objects, less strings means less error prone.
The Bad: not type safe, and a little less readable than HQL 
The Bottom line: Use only when 5 is not applicable.

5. And now you can use NQG:

   1:  string firstPostTitleName = Post.FindOne(
   2:      Where.Post.Blog.Name == "Cool Blog");

The Good: Readable, type safe.
The Bad: I do not how to invoke sql server side functions with that. And it is a little premature, so you should have solid tests. But you should have them anyway.
The Bottom line: Prefer using this method. If it fails, go to 4 or 3.

 

So IMHO it is a great tool, and I've went right away to test it and play a little with the source (I've even found and fixed a little bug !!).

Notice that I've tagged it under Linq, too, since it gives us a Linq-ish way to query the DB in a typesafe elegant manner. In VB.NET the query code looks even better.

2006 Oct 10

A Generic Execute Callback for ActiveRecord - Execute<T>

tagged as: c# | castle | activerecord

I am working with AR for a few month now, ignorantly ignoring the Castle Project's wiki.

Stupid I am. I could have learned a lot and save a bunch of wandering around the net and the intellisense to learn obvious stuff.

Thanks to hammett who pointed me there.

Anyway - now I read it from <html> to </html>, and I saw the part about running HQL using the Execute Callback

There are examples, each one with two flavors: "not using generics", and "using generics". Well, the one about the Execute Callback is misleading. It should have been "not using anonymous method" and "using anonymous methods", since the second one does not use generics.

So I thought - let's make the API simpler.

We would have like to allow the user execute her hql like that:

   1:  public static Post[] GetPostsByAuthorName(string authorName)
   2:  {
   3:      return (Post[])Execute(typeof(Post), "from Post p where p.Author = ?", authorName);
   4:  }

Or even better, by using generics (this time for real):

   1:  public static Post[] GetPostsByAuthorName(string authorName)
   2:  {
   3:      return Execute<Post>("from Post p where p.Author = ?", authorName);
   4:  }

Here is the magic:

   1:  public static T[] Execute<T>(string hql, params object[] parameters)
   2:  {
   3:      IList untypedResults = (IList)Execute(delegate(ISession session, object data)
   4:      {
   5:          object[] queryParams = (object[])data;
   6:          IQuery query = session.CreateQuery(hql);
   7:          for (int position = 0; position < queryParams.Length; ++position)
   8:              query.SetParameter(position, queryParams[position]);
   9:          return query.List();
  10:      }, parameters);
  11:      T[] results = new T[untypedResults.Count];
  12:      untypedResults.CopyTo(results, 0);
  13:      return results;
  14:  }

I'll add an overload that will accept named parameters. I am not sure about the right way to do that, though.

My options are:

   1:  Execute<T>(string hql, 
   2:      string[] paramNames, 
   3:      Type[] paramTypes, 
   4:      object[] parameters)

Or:

   1:  Execute<T>(string hql, IParameter[] parameters)

where IParameter definition is something like:

   1:  public interface IParameter<T>
   2:      where T: Type
   3:  {
   4:      public string Name { get; set;}
   5:      public T Value { get; set;}
   6:  }

Maybe both?

And maybe I haven't read the wiki thoroughly enough and there are already implementations for all that?

2006 Oct 8

Projection using ActiveRecord's ImportAttribute and HQL's select new clause

tagged as: castle | activerecord

 

WARNING:
I'm going to use some lousy examples in this post. Please bear with me, and stick to the Point rather than to the actual Classes being presented.

What is a projection?

Consider this genius ERD:

 A sample projection could be a kind of a view:

The SQL is (surprise!)

   1:  SELECT
   2:      p.Title as PostTitle, c.Content
   3:  FROM 
   4:      Comments c INNER JOIN
   5:      Posts p ON c.PostId = p.Id

But we live in the Classes/Code/Compiler/Types/etc. domain, not the SQL domain, so I'd need a Post and a Comment classes that would derive from ActiveRecordBase<>.
But what about the CommentsView?
I can select into an array of objects using a simple HQL's select:

   1:  IActiveRecordQuery query = new HqlBasedQuery(typeof(Job),
   2:      "select c.Post.Title, c.Content from Comment as c");
   3:   
   4:  ArrayList report = ActiveRecordMediator.ExecuteQuery(query) as ArrayList;

 But I do not want to, since every item in the ArrayList is of type object[]. yuck.

No, I want to use a CommentView class, and this syntax:

   1:  IActiveRecordQuery query = new HqlBasedQuery(typeof(Job),
   2:      "select new CommentView(c.Post.Title, c.Content) from Comment as c");
   3:   
   4:  ArrayList report = ActiveRecordMediator.ExecuteQuery(query) as ArrayList;

and now the ArrayList contains CommentView objects.

In order to achieve that, we need to use the peculiar named attribute, [Import] like that:

   1:  [Import(typeof(CommentView), "CommentView")]
   2:  [ActiveRecord("Comments")]
   3:  public class Comment : ActiveRecordBase<Comment> { /* blah blah */ }

Now ActiveRecord (assuming Comment class was initialized using ActiveRecordStarter) knows that CommentView refers to a projection of the Comment ActiveRecord, using the class CommentView.

The use of [Import] is not documented too well, so I've included ImportAttribute in the post's title so It could be easily found. After a few refinements I hope to post it to the CastleProject wiki.

Note Ayende's post, with some better example for projection, but it lacks the demonstration of using Import attribute, so that's actually the reason for this post.

That's for the "how you do that".

 

now for the "How I think you should be able to do that":

well, INHO, the Import attribute is poorly named.

The name of the Attribute makes no sense to me.
The lack of default name makes no sense to me. I should be able to

   1:  [Import(typeof(CommentView))] 

And what if I need some different projections to the same AR type? Multiple Import attributes make no sense, too.

Does the Import attribute serves a different purpose? If not – why not call it “Projects”? (since it projects to some other classes)

like:

   1:  [Projects(typeof(CommentProjectionOrWhatever))] 
   2:  public class Comment : ActiveRecordBase<Comment> { /* blah blah*/ }

or even better yet:

   1:  [Projects(
   2:      typeof(CommentProjectionOrWhatever), 
   3:      typeof(YetAnotherCommentProjectionNeededForDemonstrationPurposesOnly )]
2006 Sep 7

Inheritence in Castle's ActiveRecord

tagged as: c# | castle | activerecord

The reference I've used while learning to use Castl'e ActiveRecord implementation is the Blog/Post demos that can be found on Castle's site.

Let's look at the Type Hierarchy example, that can be found here.

It shows an implementation of a class diagram that look a little bit like this:
Class Diagram

Let's look at the code :

[ActiveRecord("entity"), JoinedBase]
public class Entity : ActiveRecordBase
{
   private int _id;
   [
PrimaryKey]
   public int Id
   {
      
get { return id; }
      set { id = value; }
   }
}

[
ActiveRecord("entitycompany")]
public class CompanyEntity : Entity
{
   private int comp_id;
   [
JoinedKey("comp_id")]
   public int CompId
   {
      get { return comp_id; }
      set { comp_id = value; }
   }
}

[
ActiveRecord("entityperson")]
public class PersonEntity : Entity
{
   private int person_id;
   [
JoinedKey("person_id")]
   public int PersonId
   {
      get { return person_id; }
      set { person_id = value; }
   }
}

But look what happens. since the Id property on entity is public and inherited to the subclasses, you get something like this:
Should I use .Id or .PersonId?

So there is a duplicate field here !!!. and it's not only a getter-setter thingie. It also have different private members.

My solution for this is to virtualize the base Id, and protectedize (hehe) the _id member, like this:

[ActiveRecord("entity"), JoinedBase]
public class Entity : ActiveRecordBase
{
   protected int _id;
   [
PrimaryKey]
   public virtual int Id
   {
      get { return id; }
      set { id = value; }
   }
}
[
ActiveRecord("entitycompany")]
public class CompanyEntity : Entity
{
   [
JoinedKey("comp_id")]
   public override int Id
   {
      get { return _id; }
      set { _id = value; }
   }
}
[
ActiveRecord("entityperson")]
public class PersonEntity : Entity
{
   [
JoinedKey("person_id")]
   public override int Id
   {
      get { return _id; }
      set { _id = value; }
   }
}

 
Now it makes more sence:
I should use .Id

 

And before you hit me with a big stick - I do know of ActiveRecordBase<T> . :) the above code is for demonstration purposes only, not to be Copy&Pasted to your Brand-New-Best-Erp-Ever-Made-And-Will-Make-You-Rich

2006 Aug 26

ActiveRecord Beginner's Resources

tagged as: castle | activerecord

I'll post here links for stuff that I find usefull, for people who are doing their first steps in the Castle's ActiveRecord's world.

This post is to be updated while finding more resources.

Note that this is not a replacement for the official ducomentation that can be found on Castle's website, but merely a place to do the beginner's life somewhat easier.

Posts by Hamilton *hammett* Verissimo, who is the engine behind the whole story:
http://geekswithblogs.net/hammett/articles/76697.aspx
http://geekswithblogs.net/hammett/articles/76809.aspx
make sure that you are following his blog.

An article by Ayende about using Generics with ActiveRecord:
http://www.castleproject.org/index.php/ActiveRecord,_.Net_2.0_and_Generics
as before - stay tuned to Ayende's blog for he very experienced in ActiveRecord and in NHibernate too, for the matter. He is also a very readable writer.

 

2006 Aug 26

ActiveRecordBase vs ActiveRecordMediator

So after a lot of talking about the matter, I'm starting a little (but real) project with Castle's ActiveRecord as an ORM service.

What I'm still not sure about, is weather I should inherit everything from ActiveRecordBase, or have my own base class and use ActiveRecordMediator?

Sure, I can derive my base class from ActiveRecordBase and have common behaviour for my model, but I am still not sure that I'm fully into the ActiveRecord pattern as a whole. It's tempting to exploit Castle's implementation but to keep the methods in a seperate class rather than in the model itself.

I also have some problem with the need to do FindAll, Find, etc. on each class so to expose the static methods in a typed way.

Well, I take back the last paragraph, since I could use ActiveRecordBase<> and it solves this problem.

To conclude: I tend to go with subclassing ActiveRecordBase<> as a base class for my model, and I'm starting to code (and test) that way, but I could still use the knowledge gained by people with real experience with this implementation ...

I've looked for insights on the matter on the web, and have found nothing. If anyone reading this has an insight about the matter, please comment here, so people who do their first steps in Castle's ActiveRecord implementation would have a better kick start regarding this issue.

Subscribe

Statistics

283
440

Related Books

Related Jobs

Related Ads

search page | Blog's home | About me