Batch update with lambda expression in DDS (EPiServer 7.5)
Introduction
When Dynamic Data Store was introduced in CMS 6, developers could directly use a LINQ provider to receive data from their stores. The LINQ provider has got some small improvements sense CMS 6, but there haven’t been any new big features.
I’m currently working in the Commerce team in Stockholm, and we’re using the DDS to store versions of catalog content. In some scenarios, for example when changing supported languages in the catalog, we had to update a lot of versions in DDS. Before 7.5, the only way to do this was to load all the objects, change the property, and save them all. This isn’t very good, so we added a new feature to DDS to solve the problem for us.
I’m now happy to present the first version of batch update in DDS. The batch update only supports simple scenarios in this first version, but can probably make some developers life a little bit easier.
Update<T>
In the DynamicDataStore class, we have now added a typed method called “Update<T>”, similar to “Items<T>”. The big difference is that “Items<T>” returns an IOrderedQueryable<T> object, which is a LINQ interface, while “Update<T>” returns an interface called “IUpdateQueryable<T>”. The later interface is an EPiServer interface, and contains tree methods, “Set”, “Where”, and “Execute”.
public interface IUpdateQueryable<TStore>
{
IUpdateQueryable<TStore> Set<TUpdate>(Expression<Func<TStore, TUpdate>> property, TUpdate value);
IUpdateQueryable<TStore> Set<TUpdate>(Expression<Func<TStore, TUpdate>> property, Expression<Func<TStore, TUpdate>> value);
IUpdateQueryable<TStore> Where(Expression<Func<TStore, bool>> predicate);
int Execute();
}
Set
The set method can be used to update specific properties. There are two overloads, one that sets a property to a constant value, and one that set the value using another property. Currently, the set method only supports the inline types in DDS, and types that uses type handlers (ITypeHandler) to map the type to an inline type.Inpline types are:
- System.Byte (and arrays of)
- System.Int16
- System.Int32
- System.Int64
- System.Enum
- System.Single
- System.Double
- System.DateTime
- System.String
- System.Char (and arrays of)
- System.Boolean
- System.Guid
- EPiServer.Data.Identity
Set property to constant value
The following line will update “MyString” property of all objects in the store:
Store.Update<MyObject>().Set(x => x.MyString, ”Hello World”).Execute();
Set property using a property
The following line will increase the “MyInt” property of all objects in the store:
Store.Update<MyObject>().Set(x => x.MyInt, y => y.MyInt + 1).Execute();
Only inline types directly on the store are supported
We only support inline types directly on the object. This is a limitation in this first version. If you have an object stored in DDS, which contains a reference type with inline types, you will not be able to do like this (trying to do this will result in an exception):
Update<T>().Set(x => x.MyComplecObject.MyString, “Hello World”).Execute().
Where
In most case, the update operation should only be done for some objects in the store. By using the “Where” method, just in the same way as LINQ, it’s possible to accomplish this.
Store.Update<MyObject>().Set(x => x.MyString, ”Hello World”).Where(x => x.MyInt == 3).Execute();
Execute
The execute method will, just as the name say, execute the query. The method will return number of updated rows.
Really nice!