User-defined types
Cassandra 2.1 introduced support for User-defined types (UDT). A user-defined type simplifies handling a group of related properties.
A quick example is a user account table that contains address details described through a set of columns: street, city, zip code. With the addition of UDTs, you can define this group of properties as a type and access them as a single entity or separately.
User-defined types are declared at the keyspace level.
In your application, you can map your UDTs to application entities. For example, given the following UDT:
CREATE TYPE address (
   street text,
   city text,
   zip int,
   phones list<text>
);
You create a C# class that maps to the UDT:
public class Address
{
   public string Street { get; set; }
   public string City { get; set; }
   public int Zip { get; set; }
   public IEnumerable<string> Phones { get; set;}
}
You declare the mapping once at the session level:
session.UserDefinedTypes.Define(
   UdtMap.For<Address>()
);
Once declared the mapping will be available for the lifetime of the application:
var results = session.Execute("SELECT id, name, address FROM users where id = 756716f7-2e54-4715-9f00-91dcbea6cf50");
var row = results.First();
// You retrieve the field as a value of type Address
var userAddress = row.GetValue<Address>("address");
Console.WriteLine("The user lives on {0} Street", userAddress.Street);
CQL column and C# class properties mismatch
For the automatic mapping to work, the table column names and the class properties must match (note that column-to-field matching is case-insensitive). For example, in the UDT and the C# class examples above were changed:
CREATE TYPE address (
   street text,
   city text,
   zip_code int,
   phones list<text>
);
public class Address
{
   public string Street { get; set; }
   public string City { get; set; }
   public int ZipCode { get; set; }
   public IEnumerable<string> Phones { get; set;}
}
You can also define the properties manually:
session.UserDefinedTypes.Define(
   UdtMap.For<Address>()
      .Map(a => a.Street, "street")
      .Map(a => a.City, "city")
      .Map(a => a.Zip, "zip")
      .Map(a => a.Phones, "phones")
);
You can still use automatic mapping, but you must add a call to the Map method. For example:
session.UserDefinedTypes.Define(
   UdtMap.For<Address>()
      .Automap()
      .Map(a => a.Zipcode, "zip_code")
);
Nesting User-defined types In CQL
UDTs can be nested relatively arbitrarily. For the C# driver you have to define the mapping to all the user-defined types used.
Based on the previous example, let’s change the phones column from set<text> to a set<phone>, where phone
contains an alias, a number and a country code.
Phone UDT
CREATE TYPE phone ( 
   alias text,
   number text, 
   country_code int
);
Address UDT
CREATE TYPE address ( 
   street text, 
   city text, 
   zip_code int, 
   phones list<phone>
);
Now we can update the Address class to use the Phone class:
public class Address 
{ 
   public string Street { get; set; } 
   public string City { get; set; } 
   public int ZipCode { get; set; } 
   public IEnumerable<Phone> Phones { get; set;} 
}
You have to define the mapping for both classes
session.UserDefinedTypes.Define( 
   UdtMap.For<Phone>(), 
   UdtMap.For<Address>()
      .Automap()
      .Map(a => a.ZipCode, "zip_code")
);
After that, you can reuse the mapping within your application.
var userAddress = row.GetValue<Address>("address"); 
var mainPhone = userAddress.Phones.First(); 
Console.WriteLine("User main phone is {0}", mainPhone.Alias);