CRM Development

Solutionist has designed the architecture for a new CRM system for use in the medical imaging industry.

Monday, 20 September 2010

Early Entity Framework thoughts

It's been a few weeks since my last post, but I've been reading and working with a couple of good books.


One of those was O'Reilly's Programming Entity Framework (ISBN 9780596807276).
It's not an easy read, but, then again, it's not really meant to be. The topic is huge with ramifications  across any multi-tier application.
I'm currently looking at an N-tier app with a combination of WPF, Silverlight and ASP.NET presentation layers, so having the underlying technology and architecture right is critical.
With that in mind, the sections on WCF RIA and Data services are very helpful and the worked examples are excellent to go through.


Now, behind all this is a niggle along the lines of "I've seen this before"... where? 
Well, Hibernate's been around Java world some time (Nhibernate more recently for MS) and, before that, you have J2EE's early awkward/abortive (choose your adjective) attempts at ORM using EJB 1 and 2. 
EJB3 and Hibernate now provide a data access layer with Spring or EJB3 session beans sitting above that providing declarative transaction management and access control. 
We had Data Transfer Objects (DTOs) for passing data across layers.


Moving across to .NET4 we have the DTO equivalent - i.e. POCOs or STEs or RIA Services' own cross-tier mechanism. You also have EF4 providing the ORM and data access, then WCF in it's various forms provides the service/session layer.


So, for N-tier apps, I get a feeling of it being a case of "Hello Microsoft, welcome to my world!".
It's early days and I'll see how this all goes in MS-land. Having done some prototyping, I have to say is that the MS tooling goes a good way to smoothing out a lot of bumps in the road. 
I'm still waiting for Netbeans/Eclipse/MyEclipse to get to the level of Visual Studio tooling - especially when developing UIs. 


See you back here soon.
 

Tuesday, 10 August 2010

Quartz.NET

  I haven't got round to trying Spring.NET yet, but had a play with another Java-to-.NET port: Quartz.NET.

I'm sure that there are other posts/tutorials about how to get it working, but I'll add in my twopennyworth as a step-by-step account of what I did.

1. Downloaded latest version of Quartz.NET - 1.0.2
2. Using VS2010, I created a Web Project and added references to the Quartz and Common.Logging dll's that are in the bin directory
3. For good measure I also added a reference to the log4net dll - I would be using this in the Quartz job.
4. For log4net config, I kept this separate from the application and placed a log4net.config file in project. I then referenced this in Global.asax as follows:

log4net.Config.DOMConfigurator.ConfigureAndWatch(new System.IO.FileInfo(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "log4net.config"));

My log4net config file looked like:





<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <root>
    <level value="DEBUG" />
    <appender-ref ref="RollingFileAppender"/>
  </root>

  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="logs\Logfile.log" />
    <appendToFile value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <rollingStyle value="Composite"/>
    <datePattern value="yyyyMMdd"/>
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="1000KB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%d [%t]%-5p %c [%x] - %m%n" />
    </layout>
  </appender>

</log4net>



5. Ran the database script (for SQL server) to create the relevant tables.

6. Updated the Web. Config file as follows:




  <configSections>

    <section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </configSections>







  <quartz>
    <add key="quartz.scheduler.instanceName" value="CommerceScheduler" />
    <!-- Configure Thread Pool -->
    <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
    <add key="quartz.threadPool.threadCount" value="10" />
    <add key="quartz.threadPool.threadPriority" value="Normal" />
    <!-- Configure Job Store -->
    <add key="quartz.jobStore.misfireThreshold" value="60000" />
    <!--<add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz" />-->
    <add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
    <add key="quartz.jobStore.dataSource" value="default" />
    <add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
    <add key="quartz.jobStore.clustered" value="true" />
    <add key="quartz.jobStore.lockHandler.type" value="Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz" />
    <add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz" />
    <add key="quartz.dataSource.default.connectionString" value="Data Source=Server_Name;Initial Catalog=quartz;Integrated Security=True" />
    <add key="quartz.dataSource.default.provider" value="SqlServer-20" />
    <add key="quartz.jobStore.useProperties" value="true" />
         </quartz>



7. Created a test job:


public class QuartzJob1 : IJob
{
  protected static log4net.ILog log =      log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  void IJob.Execute(JobExecutionContext context)
  {
    log.Debug("QuartzJob1 run");
  }
}

8. For testing purposes created a class with the following static method.

public static void InitQuartz()
{
    // construct a scheduler factory
    ISchedulerFactory schedFact = new StdSchedulerFactory();

    // get a scheduler
    IScheduler sched = schedFact.GetScheduler();
    sched.Start();

    // construct job info
    JobDetail jobDetail = new JobDetail("myJob", null, typeof(QuartzJob1));
    // fire every hour
    Trigger trigger = TriggerUtils.MakeMinutelyTrigger();
    // start on the next even hour
    trigger.StartTimeUtc = TriggerUtils.GetNextGivenMinuteDate(DateTime.UtcNow, 1);
    trigger.Name = "myTrigger";
    sched.ScheduleJob(jobDetail, trigger);
}

9. Global.asax added a call to InitQuartz()

10. Ran the application.

You should see a log message being written out every minute.
And you should see entries in the
QRTZ_SIMPLE_TRIGGERS and QRTZ_FIRED_TRIGGERS tables.




Friday, 6 August 2010

RIA Services and ASP.NET

I've been looking at WCF RIA services for a new project - and looking at seeing if I can use the DomainService on an ASP.NET page directly.

This gets you to a half-way house situation where you have your middle-tier, but don't have to learn Silverlight just yet. It's not immediately obvious where to start, but you need to get hold of the RIA services toolkit (for SL4... I'm working with VS2010) - which then gives you a DomainDataSource available for use on .aspx pages.

So.... created my DomainService with a couple of related entities.
pulled in a couple of DomainDataSources for the master and detail queries and hooked up a grid for the master query and DetailView for the detail.

The basic concept worked fine!

But.. then I tried to enable paging and sorting in the master and detail view and got this error

The method ‘Skip’ is only supported for sorted input in LINQ to Entities. The method ‘OrderBy’ must be called before the method ‘Skip’.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NotSupportedException: The method ‘Skip’ is only supported for sorted input in LINQ to Entities. The method ‘OrderBy’ must be called before the method ‘Skip’.
Hmmm....

It turns out (thanks to this link) that you need to add some default ordering to your query methods in the DomainService. This enforces the ordering before any other modifier.

Wednesday, 4 August 2010

Training

Running an ASP.NET training course recently got me thinking about the range of skills someone needs nowadays working in IT.

The students came from a wide range of backgrounds - some with more or less development experience, but the range of topics we were covering on was huge:
  • HTML
  • Javascript
  • C#
  • OO concepts
  • XML
  • Security
  • Database access
  • Visual Studio IDE (a course in itself!)
... and we're not even talking about particularly complex sites.
If you are talking about complex enterprise applications, then you're into services (of varying kinds), AJAX, async messaging, enterprise integration, design patterns, various competing Microsoft and Java/J2EE technologies, etc, etc

I've picked this up over many years in the industry - these students are faced with a bewildering array of information to absorb at the outset. Unfortunately, all too often, potential employers want to see the "finished" article - but it doesn't happen overnight.

I wish them well on their chosen career path - if they appreciate that being in IT means being willing to look at new ideas and continue learning, then they're a good part of the way there to appreciating what IT is as a profession.

.NET IoC

Blogging is a new departure for me, but now I've started my own company (Solutionist) - it seemed like a good time to start... so here goes...

I've been working a lot with .NET technologies lately and have been trying to pull across my
existing Java/J2EE knowledge as a frame of reference.

Something that was sorely missing was Dependency Injection - I'd become fairly hooked on Spring for that and was really missing it in Microsoft World. So, finding Spring.NET and Microsoft's own Unity framework has come as a bit of a relief. Now it's just a case of seeing which one "fits" better.

Hopefully, over the next few days as I try them both out, I'll write it up.