EF4 – Code first CTP4

Since I’m on vacation and spend all my time on SisoDb I will not cover the new release of CTP4 for Code first and Entity framework 4, but instead direct you to a fairly nice post with good external reference links. So, instead of writing something that already has been written, go to Scott Hanselman’s blog: http://www.hanselman.com/blog/SimpleCodeFirstWithEntityFramework4MagicUnicornFeatureCTP4.aspx

I like that Microsoft has made it simpler and I really like the way you now can define your model in OnModelCreating. You can of course hook in your more detailed mappings via modelBuilder.Configurations.Add(new FooMapping());

//Daniel

SisoDb – First code released

Recently I started playing with Lucene.Net and Json.Net for the reason of creating my own solution for persisting hierarchial-structures of data. The goal is to make it schemaless and really simple. The result was: SisoDb. As of right now it got support for:

  • Commitable Unit of work
  • Insert
  • Update
  • DeleteByKey
  • GetByKey

Roadmap

My focus in the next couple of spent hours will lie on:

  • Querying support both for Indexes as well as free text querying using Lucene
  • Version-control for concurrency detection
  • Some support for relations
  • Distrubuted proxy

Some basics

SisoDb persists Structures. The only demand that is puts on the structures being persisted is that they must have a property that contains a Guid which acts as the unique-identifier for the Structure. By conventions, this member should be named Id but you can configure this via schemas. It can be System.Nullable or System.Guid. You don’t have to provide a value, since SisoDb will generate this for you upon insert. Contained objects in the Structure should not have an Id-property. A Structure should be seen as an aggregate where contained objects and properties are leafs of data, either represented of simple value types (strings, ints, decimals, datetimes) or complex types (your own types). The Structure will be represented in the database as Json, which is produced using Newtonsofts Json.Net library. Which means, you can use the attributes of this library to affect how the structure is serialized and deserialized. As of right now there is one underlying provider, which stores the Structures (the Json, Key and Indexes) using Lucene.Net. I’m thinking of building a provider that uses MsSql as the storage media, but as of right now, it’s Lucene that is used.

An example

Create a Structure

The example model is really simple. A Customer-entity containing some simple properties for naming as well as Billing-address and Delivery-address, which is represented by a custom complex type, Address.

[Serializable]
public class Customer
{
    public Guid Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public ShoppingIndexes ShoppingIndex { get; set; }
    public DateTime CustomerSince { get; set; }
    public Address BillingAddress { get; set; }
    public Address DeliveryAddress { get; set; }

    public Customer()
    {
        ShoppingIndex = ShoppingIndexes.Level0;
        BillingAddress = new Address();
        DeliveryAddress = new Address();
    }
}

[Serializable]
public class Address
{
    public string Street { get; set; }
    public string Zip { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

[Serializable]
public enum ShoppingIndexes
{
    Level0 = 0,
    Level1 = 10,
    Level2 = 20,
    Level3 = 30
}

Create a Database

An instance of a SisoDatabase implementation is supposed to be long lived. It holds meta-data/schema-information about the structures being persisted. The SisoDatabase takes an IConnectionInfo which lets you define which underlying database-implementation to use as well as a connectionstring. When using the LuceneIO-provider, the connectionstring should contain the path to the directory where the data (indexes to use the correct Lucene terminology) should be stored.

var connectionInfo = new SisoConnectionInfo(StorageProviders.LuceneIo, DbPath);
var database = new SisoDatabase(connectionInfo);

This is something you would put in your IoC-container or at least in a factory.

Create a Unit-of-work & Insert a customer

The Unit-of-work is designed to be short lived. It is used for performing CRUD-operations against the database. It implements IDisposable and it’s recomended to be used in conjunction with the using-statement. If you don’t call Commit, ongoing changes aren’t flushed against the database. If you don’t use the using-statement make sure to call Dispose since it ensures that write-locks are being released.

var customer = new Customer
{
    Firstname = "Daniel",
    Lastname = "Wertheim",
    ShoppingIndex = ShoppingIndexes.Level1,
    CustomerSince = DateTime.Now,
    BillingAddress =
        {
            Street = "The street",
            Zip = "12345", City = "The City",
            Country = "Sweden"
        }
};

using (var unitOfWork = database.CreateUnitOfWork())
{
    unitOfWork.Insert(customer);
    unitOfWork.Commit();
}

Refetch and Update Customer

As of right now the only query-support is GetByKey which lets you retrieve a single item by a key-value (Guid).

using (var unitOfWork = database.CreateUnitOfWork())
{
    var customer = unitOfWork.GetByKey<Customer>(id);
    customer.ShoppingIndex = ShoppingIndexes.Level2;
    customer.Firstname = "Hans";

    unitOfWork.Update(customer);
    unitOfWork.Commit();
}

Delete Customer

As of right now you can only delete via the key-value.

using (var unitOfWork = database.CreateUnitOfWork())
{
    unitOfWork.DeleteByKey<Customer>(customer.Id);
    unitOfWork.Commit();
}

Custom key

As told, per default, you don’t have to provide any schema-information as long as the root-entity (structure) contains an Id:Guid or Id:Nullable -member. If you want to use another key-member, this is how you do it.

database.Schemas.Register<Customer>(
    builder => builder
        .SetKey(c => c.UId)
        .AddIndex(c => c.Lastname));

That’s it for now. The current code can be found here.

//Daniel

SisoDb – Some code preview

I thought I would share some code of how my SisoDb (Simple-Structure-Oriented-Db) looks like.

As of right now you have to provide info about which member contains the key. This will change and will instead be convention based.

var schemaBuilder = new ManualSchemaBuilder();
schemaBuilder.Register<Customer>(builder => builder.SetKey(c => c.Id));

You can also use SchemaBuilder.AddIndex to provide specific indexes that you wan’t to query more efficiently.

var schemaBuilder = new ManualSchemaBuilder();
schemaBuilder.Register<Customer>(
    builder => builder
        .SetKey(c => c.Id)
        .AddIndex(c => c.Lastname));

The next step is to create a database. Supported options are I/O-based or a Virtual (in-memory) database. The virtual only lasts as long as the UnitOfWork lives. The database is designed to be long-lived and is something you would keep alive, preferable using your IoC-container.

var connectionInfo = new LuceneConnectionInfo(LuceneDbTypes.Io, @"C:\#Temp\SisoDb\ConsoleSample");
var database = new LuceneDatabase(connectionInfo);

var schemas = schemaBuilder.GetSchemas();
database.RegisterSchemas(schemas);

Now we are ready to add some data, so lets create a Customer and add it using UnitOfWork

var customer = new Customer
                    {
                        Firstname = "Daniel",
                        Lastname = "Wertheim",
                        ShoppingIndex = ShoppingIndexes.Level1,
                        CustomerSince = DateTime.Now
                    };

using (var unitOfWork = database.CreateUnitOfWork())
{
    unitOfWork.Insert(customer);
    unitOfWork.Commit();
}

That’s it. If Commit() isn’t called everything is rolled back.

I will soon publish the source code on Google Code.

//Daniel

Writing my own NoSql DB?

Yesterday I got a thought:

why not write something very simple that can store object-graphs without mappings and other fuss.

Yes I know there’s MongoDb, RavenDb and several others, but it’s always a great deal of fun to write something of your own. So, inspired by Ayende’s technology choices, I spent a few hours last night just fiddling around with Lucene.Net and Json.Net. The result:

A simple model

public class Address
{
    public string Street { get; set; }
    public string Zip { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

public class Customer
{
    [Key]
    public Guid? Id { get; set; }

    [Index]
    public string Firstname { get; set; }

    [Index]
    public string Lastname { get; set; }

    [Index]
    public int ShoppingIndex { get; set; }

    public Address BillingAddress { get; private set; }
    public Address DeliveryAddress { get; private set; }

    public Customer()
    {
        BillingAddress = new Address();
        DeliveryAddress = new Address();
    }
}

Consuming a Storage-provider

var customer = new Customer
                    {
                        Id = Guid.NewGuid(),
                        Firstname = "Daniel",
                        Lastname = "Wertheim",
                        ShoppingIndex = 99
                    };
customer.DeliveryAddress.Country = "Sweden";

var store = new LuceneStructureStore();
store.Insert(customer);

var refetched = store.GetByKey<Customer>(customer.Id.ToString());
...
...

Maybe it will grow to something useful. In the meantime I will continue my work with my MongoDB-provider, Simple-MongoDB.

//Daniel

Dealing with Enumerations and Entity framework 4 – code first

If you have an entity with an enumeration and you wan’t to store it using Entity framework 4, Code-only, you might run into problem. The convention-based mapping is sufficent for generating the schema but you will run into problem when trying to create an objectset.

The solution that I will present here is kind of simple: Make a custom-type that you map as a complex-type using ComplexTypeConfiguration, then you implement implicit operator overloading to provide implicit-conversion between this custom-type and the enumeration.

The Entity

public class Tifi : ICamyinEntity
{
    public Guid Id { get; set; }

    public byte[] Version { get; set; }

    public TifiType Type { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }

    public string Source { get; set; }
}

The Enumeration

public enum TifiTypes : int
{
    Undefined = 0,
    Blog = 1,
    Video = 2
}

The Custom-type

public class TifiType
{
    public int Value { get; private set; }

    private TifiType()
        : this(default(TifiTypes))
    {}

    public TifiType(int value)
    {
        Value = value;
    }

    public TifiType(TifiTypes type)
    {
        Value = (int)type;
    }

    public static implicit operator int(TifiType type)
    {
        return type.Value;
    }

    public static implicit operator TifiType(int value)
    {
        return new TifiType(value);
    }

    public static implicit operator TifiTypes(TifiType type)
    {
        return (TifiTypes)type.Value;
    }

    public static implicit operator TifiType(TifiTypes type)
    {
        return new TifiType(type);
    }
}

The Mappings

public class TifiTypeMapping : ComplexTypeConfiguration<TifiType>, ICamyinMapping
{
    public TifiTypeMapping()
    {
        Property(o => o.Value);
    }
}

public class TifiMapping : EntityConfiguration<Tifi>, ICamyinMapping
{
    public TifiMapping()
    {
        HasKey(o => o.Id);
        Property(o => o.Id)
            .StoreGeneratedPattern = StoreGeneratedPattern.Identity;

        Property(o => o.Version)
            .IsConcurrencyToken()
            .IsRequired()
            .HasStoreType("timestamp")
            .StoreGeneratedPattern = StoreGeneratedPattern.Computed;

        Property(o => o.Source)
            .HasMaxLength(200)
            .IsUnicode()
            .IsRequired();

        Property(o => o.Title)
            .HasMaxLength(100)
            .IsUnicode();

        Property(o => o.Description)
            .HasMaxLength(1000)
            .IsUnicode()
            .IsOptional();
    }
}

That’s it. You will now be able to assign enumeration values to an instance of Tifi and it’s member Type.

var tifi = new Tifi
{
    Title = "My first Tifi",
    Description = "This works",
    Source = "http://daniel.wertheim.se",
    Type = TifiTypes.Blog
};

//Daniel

Entity framework 4 – CTP3 – Complex type mapping

I got a question on my last post of how complex type mapping should be dealt with so I fired up Visual Studio and put together something.

What you need to do as a consumer of the lib

Lets say my Customer has a property Address and I want to store it in the Customer-table, or more correctly, “together with the Customer entity” as an embedded object.

Step 1 – Create the Address class

[Serializable]
public class Address
{
    public string Street { get; set; }
    public int? Zip { get; set; }
}

Step 2 – Add it to the Customer

[Serializable]
public class Customer
    : IEntity
{
    public int Id { get; set; }

    public byte[] Version { get; set; }

    public string Firstname { get; set; }

    public string Lastname { get; set; }

    public EfAddress Address { get; set; }

    public string Name
    {
        get { return string.Format("{0} {1}", Firstname, Lastname).Trim(); }
    }

    public Customer()
    {
        Address = new Address();
    }
}

Note! You must set-up an instance of the Address, otherwise you will get an exception, complaining about an null-address.

Step 3 – Map the Complex type

[Serializable]
public class AddressMapping
    : ComplexTypeConfiguration<Address>
{
    public AddressMapping()
    {
        Property(o => o.Street)
            .HasMaxLength(50)
            .IsUnicode()
            .IsOptional();
        Property(o => o.Zip);
    }
}

Instead of extending EntityConfiguration<T> you extend ComplexTypeConfiguration<T>, then just provide the mappings just as you would do with an entity.

That’s it! You are done. The generated table will now contain fields like: Address_Street; Address_Zip. If you like to control the namings of the fields: use MapSingeType inside of the AddressMapping-class.

The changes to get it to work

To get it to work I had to add one method to the EfObjectContextBuilder, namely: RegisterComplexType as well as tweak RegisterMappings.

/// <summary>
/// Registers a complex-type.
/// </summary>
/// <typeparam name="TComplex">The complext-type being mapped.</typeparam>
/// <param name="mapping">The mapping-configuration.</param>
public void RegisterComplexType<TComplex>(ComplexTypeConfiguration<TComplex> mapping)
{
    Configurations.Add(mapping);
}

The Assembly resolvers (EfMappingsResolverByAssemblyScan, EfMappingsResolverByInterfaceFilterType) will locate the AddressMapping-type and I have updated EfObjectContextBuilder public void RegisterMappings(IEfMappingsResolver mappingsResolver) so that it will handle both EntityConfiguration<T> as well as CompexTypeConfiguration<T>

/// <summary>
/// Registers a pluraized Entity-Set as well as the mappings for an Entity by
/// traversing the Types of <see cref="EntityConfiguration{TEntity}"/> returned
/// by the Resolver.
/// </summary>
/// <param name="mappingsResolver">The mappings resolver.</param>
public void RegisterMappings(IEfMappingsResolver mappingsResolver)
{
    var mappingTypes = mappingsResolver.Resolve().ToList();

    if(mappingTypes.Count < 1)
        throw  new DataException(string.Format(StorageExceptions.EfObjectContextBuilder_RegisterMappings, typeof(IEfMappingsResolver).Name));

    var registerMapping = GetType().GetMethod("RegisterMapping");
    var registerComplexType = GetType().GetMethod("RegisterComplexType");

    foreach (var mappingType in mappingTypes)
    {
        var configurationType = mappingType.BaseType;

        var registrationMethod = (configurationType.Name.StartsWith("ComplexTypeConfiguration"))
                                        ? registerComplexType
                                        : registerMapping;

        var typeBeingConfigured = configurationType.GetGenericArguments()[0];
        var generic = registrationMethod.MakeGenericMethod(typeBeingConfigured);
        generic.Invoke(this, new[] { Activator.CreateInstance(mappingType) });
    }
}

If you are consuming the internals of the ContextBuilder you can use ComplexType<T>() which will return a ComplexTypeConfiguration instance that’s allready hooked up to the ContextBuilder.

The code can be downloaded here. Note!, I have provided the complete solution of my Core-lib. The code you are interested in is located in the project: Pls.Core.Storage under the namespace Ef. If you look at the IntegrationTestsOf-project, you will find EfCustomer and EfAddress etc. The naming is due to the fact that Entity framework can’t handle two classes having the same name within one assembly. Since I have a Linq to SQL implementation in there as well, I had to name them “L2SqlCustomer” and “EfCustomer“.

//Daniel

Entity framework 4 – CTP3 – Code first vs Linq to Sql

I just started doing some architectural changes to my old code in my previous article for Entity framework 4 (EF4) and at the same time updating it to use the new CTP3 add-on as well as writing the same code for Linq to Sql (L2Sql). I didn’t find any incompatibilities when updating from CTP2 to CTP3 but I did find something annoying. The Entity framework team is aware of this bug and will try to resolve this issue in the future.

This article shows you a solution where you DON’T use a designer or wizard for designing your model, it focuses on “Code first” where the entities are designed manually in code, as pure POCOs.

1 – The design

The design of my solution for dealing with storage of entities, has the following main components: Mappings-resolver, Storage-provider and Unit-of-work. A part from these there’s an ObjectContext and an ObjectContextBuilder, which you don’t have to deal with explicitly, since they are consumed by the Storage-provider and the Unit-of-work. The interface definition of a Storage-provider and the Unit-o-work, looks like this:


Interface for Storage-provider & Unit-of-work

1.1 – Mappings-resolver

The Mappings-resolver is responsible for finding the types that are to be handled by the Storage-provider; in other words, it locates your entities which are provided to the ObjectContextBuilder so that it can register mapping-information for each found entity and later on pass this information on to each created ObjectContext. For L2Sql, the mappings are described using attributes in the entity itself and the mappings are contained in an AttributeMappingSource. For EF4, the mappings are described using the fluent-API of the EntityConfiguration<T> class (more examples of this in the code section below).


L2Sql – Mappings-resolver


EF4 – Mappings-resolver

Both L2Sql and EF4 has two different Mapping-resolver implementations. One that scans for types in a specified assembly, and one that scans for types in the assembly that contains the interface that is provided via generics. With the second approach, the types also need to implement this interface, hence it acts as a filter, indicating if a type should be included or not. No matter which mappings-resolver you choose, all types needs to be a non-abstract class.

1.1.1 – L2SqlMappingsResolver

The L2Sql implementation looks for types that are classes that isn’t abstract and that are decorated with the attribute: TableAttribute. Each found type is then registered with the MappingSource’s model.

1.1.2 – EFMappingsResolver

The EF implementation looks for types that are classes that: isn’t abstract; extends EntityConfiguration<T>;where the name ends with Mapping.

1.2 – Storage-provider

The Storage-provider is designed to be long lived whilst the Unit-of-work is designed to be short-lived. The Storage-provider is tied to a certain implementation like: EF4 or L2Sql. It’s main responsibility is to create new instances of Unit-of-works, which then is used to-do CRUD-operations against the data source specified in the connection string passed to the Storage-provider. If you are familiar with NHibernate, you can look at the storage-provider as the Session factory.

1.3 – Unit-of-work

The Unit-of-work is designed to be short lived. It wraps the ObjectContext and provides a common API independent of the actual implementation (EF4 or L2Sql). It implements IDisposable so that you can use it in conjunction with an using-block. You use it to perform inserts, updates and deletes as well as for querying your model. When performing insert, updates and deletes, you have to flush your changes. You can see the Flush-operation as a sort of commit. Note! It’s not using transactions. If you want to use database transactions, you can i.e use the TransactionScope, or extend the Storage-provider to have a member: CreateUnitOfWorkWithTransaction() : ITransactionalUnitOfWork; or something like that.

L2Sql & EF4, Storage-provider and Unit-of-work

1.4 – ObjectContextBuilder & ObjectContext

The ObjectContextBuilder is responsible for holding mappings (added by passing a mappings-resolver to RegisterMappings) and for creating new instances of ObjectContexts, which are injected to the UnitOfWork instances.

1.4.1 – L2SqlObjectContext

As of right now this class just extends the DataContext class. It’s there to bring some consistency in the namings of all the components involved in the L2Sql-implementation. It might get extended in the future, but for now, it’s only implemented to bring consistency, so that L2SqlObjectContextBuilder and L2SqlUnitOfWork can work with L2SqlObjectContext rather than DataContext.

1.4.2 – EfObjectContextBuilder & ObjectContext

The EF4-implementation of ObjectContextBuilder, it extends the allready existing ContextBuilder. Also note that the EF4 ObjectContextBuilder holds a couple of alternative ways to register mappings, but as long as you use the Storage-provider, you don’t have to care about these. But if you want to extend something or use the builder directly, these members are there to let you add mappings.


L2Sql & EF4 – ObjectContextBuilder & ObjectContext

2 – How to consume the lib

That was a very brief and abstract explanation of the parts involved, now lets take a look at how to consume the lib.

2.1 – L2Sql

Step 1 – Define the model & the mappings

The entity can be placed freely in your assembly and doesn’t have to be generated by the DBML-designer. The example we are dealing with a very simple Customer class. Although I can specify mappings with XML in L2Sql, I tend to like the attribute-decoration approach more easygoing and clear, since I don’t have to locate a certain xml-file for managing the mappings.

[Serializable]
[Table(Name = "Customers")]
public class Customer
{
    [Column(Name = "CustomerId", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int Id { get; set; }

    [Column(IsVersion = true, IsDbGenerated = true, CanBeNull = false, AutoSync = AutoSync.Always)]
    public byte[] Version { get; set; }

    [Column(CanBeNull = true, DbType = "NVARCHAR(100)")]
    public string Firstname { get; set; }

    [Column(CanBeNull = true, DbType = "NVARCHAR(100)")]
    public string Lastname { get; set; }

    public string Name
    {
        get { return string.Format("{0} {1}", Firstname, Lastname).Trim(); }
    }
}

Nothing spectacular. I have chosen to have an Id-field that is set-up as an identity as well as a Version-field for concurrency detection.

Step 2 – Extract the mappings

The ObjectContextBuilder needs to know where the data source is as well as what mappings to be used, hence we need to provide a connection string as well as a MappingsResolver.

Alternative 1

var mappingsResolver = new L2SqlMappingsResolverByAssemblyScan(assemblyWithEntities);

In the code above, I have chosen to go with a resolver that extracts the mappings from an assembly that contains my Linq-entities and the attribute-mappings (the Customer).

If I would like to I could let all my entities implement a certain interface and use it to extract the entities. The resolver will then look at the assembly containing the interface, and will look for the classes that implements this interface. To use this solution, I just need to use another resolver:

Alternative 2

var mappingsResolver = new L2SqlMappingsResolverByInterfaceFilterType<IEntity>();
Step 3 – Create a Storage-provider

After having defined my mappings and selected a strategy for fetching them (Step 1 & 2), I can now create my long-lived Storage-provider. Just give it a valid connection string for a Ms-Sql database and the mappings-resolver.

var storageProvider = new L2SqlStorageProvider(connectionString, mappingsResolver);

The rest of the Steps are common between the L2Sql and EF4 implementation, so before proceeding with Step 4, lets look at the EF4-implementation of Step 1 – 3.

2.2 – EF4

Step 1 – Define the model & the mappings

With the EF4 solution, the class doesn’t contain the attributes, instead the mappings are configured in a separate class, using the fluent-API of the EntityConfiguration-class.

public interface IEntity
{
    int Id { get; set; }
    byte[] Version { get; set; }
}

[Serializable]
public class Customer
    : IEntity
{
    public int Id { get; set; }

    public byte[] Version { get; set; }

    public string Firstname { get; set; }

    public string Lastname { get; set; }

    public string Name
    {
        get { return string.Format("{0} {1}", Firstname, Lastname).Trim(); }
    }
}

I have chosen to let my entities implement a certain interface so that I can re-use some mappingconfiguration by having a base-class for my mappings (EntityMapping<T>)

[Serializable]
public class EntityMapping<T> : EntityConfiguration<EfCustomer>
    where T : IEntity
{
    protected EntityMapping()
    {
        HasKey(o => o.Id);
        Property(o => o.Id)
            .IsIdentity();
        Property(o => o.Version)
            .IsConcurrencyToken()
            .IsRequired()
            .HasStoreType("timestamp")
            .StoreGeneratedPattern = StoreGeneratedPattern.Computed;
    }
}

[Serializable]
public class CustomerMapping
    : EntityMapping<EfCustomer>
{
    public CustomerMapping()
    {
        Property(o => o.Firstname)
            .HasMaxLength(100)
            .IsUnicode()
            .IsOptional();
        Property(o => o.Lastname)
            .HasMaxLength(100)
            .IsUnicode()
            .IsOptional();
    }
}
Step 2 – Extract the mappings

When dealing with the EF4-solution the types to be extracted by the MappingsResolver isn’t the entities but instead the Mapping-classes. This is done using one of two alternatives:

Alternative 1

var mappingsResolver = new EfMappingsResolverByAssemblyScan(assemblyWithEntities);

Alternative 2

var mappingsResolver = new EfMappingsResolverByInterfaceFilterType<IEntityMapping>();

In the Alternative 2 the IEntityMapping could be an empty interface definition that is implemented by the mapping-classes.

Step 3 – Create a Storage-provider

After having defined my mappings and selected a strategy for fetching them (Step 1 & 2), I can now create my long-lived Storage-provider. Just give it a valid connection string, a providername (System.Data.SqlClient used by the DbProviderFactory) and the mappings resolver.

var storageProvider = new EfStorageProvider(connectionString, providerName, mappingsResolver);

That’s it. Now we have gone through all the implementation-specific scenarios. The rest of the steps are common between the L2Sql and EF4 implementation.

2.3 – The Unit-of-work

So the steps up until now has been specific depending on the selected solution: L2Sql or EF4. How you consume the Unit-of-work isn’t solution specific, so from now on, there will only be one set off code examples.

Create the data source

When doing integration testing it’s very useful to be able to teardown and set-up a new database.

storageProvider.SetupDataStore();
Consume the Unit-of-work

Remember that the Unit-of-work is supposed to be short-lived. It contains the instance of the underlying DataContext and provides CRUD-operations.

Insert single

var customer = new Customer {Firstname = "Daniel", Lastname = "Wertheim"};

using(var unitOfWork = storageProvider.CreateUnitOfWork())
{
    unitOfWork.Insert(customer);
    unitOfWork.Flush();
}

Insert many

var customers = new List<Customer>
                    {
                        new Customer {Firstname = "C", Lastname = "1"},
                        new Customer {Firstname = "C", Lastname = "2"}
                    };

using(var unitOfWork = storageProvider.CreateUnitOfWork())
{
    unitOfWork.InsertMany(customers);
    unitOfWork.Flush();
}

Update
There’s no real Update method, the way to see it is that either an entity belongs to the context (unit-of-work) or it doesn’t. If it where created in another context then the one you are using for updating it, you have to attach it to the new context. Sort of “letting the context be aware of the existence of the entity“. For this I use AttachAsModified.

var customer = new Customer { Firstname = "Daniel", Lastname = "Wertheim" };

using (var unitOfWork = storageProvider.CreateUnitOfWork())
{
    unitOfWork.Insert(customer);
    unitOfWork.Flush();
}

using (var unitOfWork = storageProvider.CreateUnitOfWork())
{
    customer.Firstname = "Scott";

    unitOfWork.AttachAsModified(customer);
    unitOfWork.Flush();
}

Delete
Just as with Update, if I work with entities created/fetched by another context (unit-of-work) I need to attach them to the new context. Although, when deleting, I don’t need to know each individual change of the entity’s properties, hence AttachMany will do.

var customers = new List<Customer>
                    {
                        new Customer {Firstname = "C", Lastname = "1"},
                        new Customer {Firstname = "C", Lastname = "2"}
                    };

using(var unitOfWork = storageProvider.CreateUnitOfWork())
{
    unitOfWork.InsertMany(customers);
    unitOfWork.Flush();
}

using(var unitOfWork = storageProvider.CreateUnitOfWork())
{
    unitOfWork.AttachMany(customers);
    unitOfWork.DeleteMany(customers);
    unitOfWork.Flush();
}

Querying
For querying you just make use of the Query method, which returns an IQueryable. Hence you can write linq-expressions or use lambdas to query it.

var customers = unitOfWork.Query<Customer>().Where(c => c.Firstname == "Daniel").ToList()

3 – Wrap up

So this was kind of an simple introduction, but it gives you a starting point to elaborate from. If I will make a follow-up it will be about mappings. But until then, for EF4 you can read about my old writings about mappings (different model and different infrastructure code):

The L2Sql and EF4 implementations can be downloaded here. I have zipped the entire solution. The project you are interested in is “Pls.Core.Storage“.

//Daniel

Entity framework 4 – CTP3 – Code first – Bug

So I finally got some time to start looking at Code first with the Entity framework CTP3 add-on, again. While doing some testing in a test library, where I have two different StorageProviders: One for Linq to Sql and another for Entity framework 4; I found something I call a bug.

I have two classes that shares nothing except that they lie in the same assembly and have the same name. One of them is decorated with mapping attributes for L2Sql and the other has no mapping attributes, but is instead mapped via the EntityConfiguration class, used by EF4.
The Customer classes lies in different namespaces and doesn’t share any specific base-class or interface.

First I register an ObjectSet/EntitySet and then the mappings (EntityConfiguration) for the Ef.Customer with my Contextbuilder. When I then invoke CreateObjectSet() I get promted with the exception:

Schema specified is not valid. Errors:
The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type ‘Customer’. Previously found CLR type ‘Pls.IntegrationTestsOf.Core.Storage.L2Sql.TestModel.Customer’, newly found CLR type ‘Pls.IntegrationTestsOf.Core.Storage.Ef.TestModel.Customer’.

My opinions: If I specify the Ef.Customer with generics the EF-infrastructure shouldn’t care about the L2Sql.Customer. They aren’t the same. They don’t share anything except lying in the same assembly an having the same name.

Bug or by design? What do you think? Or have I done it wrong?

//Daniel

Simple-MongoDB – Part 2, Anonymous types, JSON, Embedded entities and references

This is the second article of me showing some features in the Simple-MongoDB driver. This time I will explore more ways of inserting data. More specifically, I will look at how-to insert Anonymous types as well as how-to insert entities described with JSON. Finally we will look at how to deal with embedded documents and relationships between entities, so called references.

Other writings in this series

Sample code

The sample code from this second article, is available for download here. Note! It also contains the code from previous parts in this series, but there has been some updates to the code, hence if you want to get your hands on the code for a specific article, use the download link in that specific article.

Flexibility

One of my goals with my driver was that it shouldn’t be tied to a certain key-value based class, like the Document-class in the MongoDB-CSharp-driver. I know that the team behind that driver, currently are implementing this as well. Simple-MongoDB relies on JSON.Net from Newtonsoft for dealing with serialization and deserialization of objects, hence I get support for dealing with anonymous types, JSON etc. Let’s look at how it get reflected in the API.

Anonymous types

The Entitystore lets you store anonymous types but will then not be able to automatically insert the document in the correct collection, which means that you have to manually specify the entity name. Note, that I wrote “the entity name” and NOT the collection name. Why? Because the Entitystore works with entities and will i.e pluralize the specified entity name (if you haven’t turned off pluralization, which is enabled by default).

Insert using anonymous type

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession(Constants.ConnectionStringName))
{
    var entityStore = new SimoEntityStore(session, Constants.DatabaseName);

    var note = new
                    {
                        Text = "This is a note, created using anonymous type.",
                        Tags = new[] { "Anonymous types", "Part 2" }
                    };

    entityStore.Insert("Notes", note);
}

Raw JSON

You can of course write/generate the JSON and pass that to the Entitystore. Again, just as with anonymous types, you have to specify the entity name.

There’s also a class “SimoJson” that takes a raw JSON-string in the constructor. If you are dealing with raw JSON, it’s preferred to use the SimoJson-class.

Insert using raw JSON

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession(Constants.ConnectionStringName))
{
    var entityStore = new SimoEntityStore(session, Constants.DatabaseName);

    var rawJson = @"{
        Text : ""This is a note, created using raw Json-string."",
        Tags : [""Raw Json-string"", ""Part 2""] }";

    entityStore.Insert("Notes", rawJson);
}

Insert using raw JSON

var json = new SimoJson(@"{
    Text : ""This is a note, created using SimoJson-type."",
    Tags : [""SimoJson-type"", ""Part 2""] }");

entityStore.Insert("Notes", json);

Embedded documents

MongoDB supports embedded documents, and I like to see them as value-object (as in the context of Domain-driven design). The embedded document has the same lifetime as the entity that it’s assigned to, hence it’s not the same as a relationship.

Insert a Note with an embedded Note

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession(Constants.ConnectionStringName))
{
    var entityStore = new SimoEntityStore(session, Constants.DatabaseName);

    var note = new Note
                        {
                            Text = "This is a note with an embeded note, created using entity.",
                            Tags = new[] { "Note with embeded note", "Part 2" },
                            SubNote = new Note{Text = "This is a subnote that is embeded."}
                        };

    entityStore.Insert<Note>(note);
}

References

MongoDB supports references and to make use of them in Simple-MongoDB, you consume the SimoReference-class or the SimoReference-class. The generic version lets you specify the type of the _id-field. Currently, it supports:

  • Guid
  • int
  • long
  • string

Read more about the different types.

To use the standard MongoDB _id-hash, use the SimoReference-class. It will generate the hash from date-time, computer, sequence etc. The Reference holds information about, in which collection the referenced document exists and which _id-value it has.

Insert a Note with a reference

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession(Constants.ConnectionStringName))
{
    var entityStore = new SimoEntityStore(session, Constants.DatabaseName);

    var user = new User {Username = "daniel"};

    var note = new Note
    {
        Text = "This is a note with an embeded note, created using entity.",
        Tags = new[] { "Note with embeded note", "Part 2" },
        WriterReference = entityStore.Reference<User>(user._id)
    };

    entityStore.Insert(user);
    entityStore.Insert(note);
}

The EntityStore.Reference function uses generics to specify to collection and the _id-value comes from the entity. Both Note and User extends Entity, which contains a property _id : SimoId. I use the SimoAutoId as the statebag so that I don’t have to manually ensure that the _id : SimoId gets a generated _id-value. I could have done this in the constructor by using SimoId.NewId().

One simple query

So, I will finish with showing you how-to perform queries using an Entity as template. The next article will deal with the various querying techniques, and by then I will hopefully have simplified the querying of references.

Query using Entity as template

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession(Constants.ConnectionStringName))
{
    var entityStore = new SimoEntityStore(session, Constants.DatabaseName);
    var selector = new Note
    {
        _id = null,
        Text = "This is a note with an embeded note, created using entity."
    };

    var notes = entityStore.Find<Note>(selector);
}

The _id is autogenerated in the Note’s base class Entity, and we want to query all notes having the text, hence we need to null the _id.

That’s it for now. Don’t forget to download the sample-code.

//Daniel

Simple-MongoDB – Part 1, Getting started

So, I thought it was time for me to write a “Getting started with MongoDB” article but instead of using Sam Corder’s driver, I will use my own: “Simple-MongoDB”. It will be a series of posts covering this topic. This post is the first and will cover how-to get connected and how-to add some entities.

Requirements

  • You have MongoDb up and running. If not, just go to “http://www.mongodb.org” and download the server part and start it. You can also read the first part of my earlier writings: Getting started with MongoDB – Using Json.Net and Castle Dynamic proxy
  • Visual Studio 2010 – I have built the driver using VS2010 and have targeted the 4.0-framework. I guess there would be quite easy to port it to a former version.

Step 1 – Download Simple-MongoDB

Head over to the project site: http://code.google.com/p/simple-mongodb and download the code. There’s two Zip-files:

  • Pls-SimpleMongoDb – v[X]-Bin.zip: Contains the release-compiled dll
  • Pls-SimpleMongoDb – v[X]-Source.zip: Contains the Visual Studio 2010 Solution

The latest code is of course available via the Trunk.

Step 2 – Create a new project

Create a new project and add a reference to the Pls.SimpleMongoDB.dll (if you test with an Console-application, ensure that to switch to Full .Net 4.0 framework and not just Client profile).

Step 3 – Get connected with the MongoDB server

This article shows how to consume the App.config and shows how to manually use the sessionfactory, which is something you probably would let your IoC handle for you.

App.config – Connectionstring

<connectionStrings>
  <add name="Pls.Simo.GettingStarted" connectionString="host:localhost;port:27017"/>
</connectionStrings>

Establish a connected Session

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession("Pls.Simo.GettingStarted"))
{
    //...
}

If you want to go with the default values from MongoDB {host : localhost, port : 27017 }; you can just use the sessionFactory.GetSession() – overload instead:

using (var session = sessionFactory.GetSession())
{
    //...
}

Step 4 – Add some data

Simple-MongoDB is designed to work with typed-classes, anonymous types as well as JSON-strings. We will start by looking at the typed-classes scenario. The simplest way to store entities is by consuming the EntityStore-API. It lies on-top of the Session-API and is designed to work with entities. The type-name of an entity is implicitly used as the collectionname and by default, consumes Microsofts Pluralizer to pluralize namings. This can of course be turned of (entityStore.Session.Pluralizer.Disable();).

Using the EntityStore-API

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession("Pls.Simo.GettingStarted"))
{
    var entityStore = new SimoEntityStore(session, "MyDatabase");

    var interestingUrl = new InterestingUrl(@"http://daniel.wertheim.se") { Description = "Some good writings about the Simple-MongoDB driver." };
    interestingUrl.SetTags("Simple-MongoDB", "Blog");
    entityStore.Insert(interestingUrl);
}

You can of course consume the Session-API, if you want. It also contains some methods that the EntityStore doesn’t. The Session-API lets you get references to databases and collections, and the work with them in a way that mimics MongoDB.

Using the Session-API

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession("Pls.Simo.GettingStarted"))
{
    var db = session["MyDatabase"];
    var collection = db.GetCollection<InterestingUrl>();

    var interestingUrl = new InterestingUrl(@"http://code.google.com/p/simple-mongodb") { Description = "The home of the Simple-MongoDB driver." };
    interestingUrl.SetTags("Simple-MongoDB", "Project site");
    collection.Insert(interestingUrl);
}

You can of course get a reference to the collection by specifying a string. But remember to take control of the pluralization.

var collection = session["MyDatabase"]["InterestingUrls"];

Step 5 – Querying

You can query by sending: either a JSON-string, anonymous-typ, typed C# class; as the selector to the Find-methods. There is a Fluent querying API that lets you help with the generation of JSON-query strings. To get more info on querying, look here: http://www.mongodb.org/display/DOCS/Advanced+Queries

Using anonymous type

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession("Pls.Simo.GettingStarted"))
{
    var entityStore = new SimoEntityStore(session, "MyDatabase");

    var interestingUrl = entityStore.FindOne<InterestingUrl>(new { Url = @"http://daniel.wertheim.se" });
}

Using Query-expression
The query-expression operates on the fluent Query-API and translates the query to JSON, which is then passed to the selector.

var sessionFactory = new SimoSessionFactory();
using (var session = sessionFactory.GetSession("Pls.Simo.GettingStarted"))
{
    var entityStore = new SimoEntityStore(session, "MyDatabase");

    var interestingUrl = entityStore.FindOne<InterestingUrl>(
        q => q["Url"].IsEq(@"http://code.google.com/p/simple-mongodb").And("Tags").HasAll("Simple-MongoDB", "Project site"));
}

That’s it for now. The next post will be posted shortly and will deal with Querying.

Download sample with code from this article.

//Daniel