WCF Server w/ Caching

Posts   
 
    
NMcGuire
User
Posts: 3
Joined: 17-Sep-2008
# Posted on: 17-Sep-2008 18:04:46   

LLBLGen 2.6 Final .NET 3.5

Here's the thing:

We have several different processes all talking to a set of three databases. Currently, we're having some concurrency issues, so we're wanting to create a WCF service that brokers all access to the data. Our plan is to make any requested changes via well-defined service operations, like

SetShiftStartTime(int ShiftId, DateTime StartTime)

rather than just exposing CRUD funtionality.

Because this is going to be the only application changing data in the database (all other apps will be re-worked to talk through this service) it seems that we should be able to cache the data that we use, launching either asynchronous persistance or going ahead and passing the changes down right away.

Each of the services that make a change will return whether or not the change was successful, and a string that will contain (potentially) a reason for the failure. The other option would be to pass back to projected data of the entity.

I have a few questions regarding this set up:

  1. The Context object, according to the docs, is not for caching, but rather for uniquing. I understand this. But could it be used for caching in a case like this, were we to call
context.GetAll(typeof(ShitEntity))

, for example? Or maybe we should just keep them local in EntityCollections and use the Context for what it was meant to do - making sure that the entity objects stay unique.

  1. We're trying to limit dependence of the client code on libraries which may change over the course of time, so are trying to decide whether to use the Adapter EntityClasses or to have a defined DataContract, and then using a partial class to add a public property that creates an instance of the DataContract. One reason for this is limiting what fields are visible in the retrieved entity (Could also define a couple fewer EntityFieldProjectors)

  2. Caveat: The following tests were run using a three field DataContract as the "Custom Class" as defined here:

    [DataContract(Name="TimeClockEmployee")]
    public class TimeClockEmployee
    {
        [DataMember(Name = "EmployeeKey")]
        public string EmployeeKey;

        [DataMember(Name = "FirstName")]
        public string FirstName;

        [DataMember(Name = "LastName")]
        public string LastName;
    }

I used a few tests to see if using the LLBLGen Projector would be faster to project onto a custom DataContract, a new EntityCollection<EmployeeEntity> or to use the property to instantiate the DataContract, with and without caching in the Context, (code available if you want it).

I found that using the context to cache the objects was ~10 times faster than pulling from the database with each call. Granted, this was against a single table with 1337 (not leet, 1,337) rows, but the (Note that TimeClockEmployee is a DataContract)

return context.GetAll(typeof(EmployeeEntity)).Select(e => ((EmployeeEntity)e).TimeClockEmployee).ToArray();

call took so little time that (DateTime start - DateTime stop).Ticks was 0. (Granted, granularity of 1/64 seconds, but still). Projecting onto the DataContract was almost as fast, ranging from 1/64 to 3/64 second, but projecting onto a new EntityCollection was as slow as going to the database again (perhaps because it did?)

Hold on - going to fire up SQL Server Profiler...

Nope, only hit the database once, but projecting onto a new EntityCollection<EmployeeEntity> took 10-20 times as long as projecting onto the custom class.

  1. Is there any way to get something besides a
List<IEntityCore>

from context.GetAll(Type t)? For example, an overload like

List<T> GetAll<T>()

would be nice, since the T would define the type you're looking for. I'll have to dig in the source code to see how hard this would be to add. As it is, what I end up doing is

List<EmployeeEntity> employees = context.GetAll(typeof(EmployeeEntity)).Select(e => (EmployeeEntity)e).ToList()
  1. Security is going to be transport, with Windows credentials, since we use a domain, and everyone who needs access has a domain account, but thanks to WCF, this is easily changeable.

  2. Any suggestions form the team here as to why this would not work? Any thoughts on features of LLBLGen that I missed? Suggestions as to better ways to do what we're looking for?

Thanks,

Neil McGuire