Mapping Objects/Classes to CRM entities

Using the XrmFieldMappingAttribute we can map object properties to CRM entity attributes. We simply decorate our class with the attributes like so:
    using Streamsol.Crm;
    using Streamsol.Crm.XrmDevelopmentToolkit;

    /// <summary>
    /// A custom object that will be mapped to an entity within the CRM organization
    /// </summary>
    [XrmEntity("contact")]
    public class Person : IXrmEntity
    {
        public Guid Id { get; set; }

        [XrmFieldMapping("firstname")]
        public string FirstName { get; set; }

        [XrmFieldMapping("lastname")]
        public string LastName { get; set; }

        [XrmReferenceType("account")]
        [XrmFieldMapping("parentcustomerid", CrmType = AttributeType.Customer)]
        public XrmReference Account { get; set; }

        [XrmFieldMapping("createdon", CrmType = AttributeType.DateTime)]
        public DateTime CreatedOn { get; set; }

        [XrmFieldMapping("statecode", CrmType = AttributeType.State)]
        public string State { get; set; }

        [XrmFieldMapping("statuscode", CrmType = AttributeType.Status)]
        public XrmStatusInfo Status { get; set; }

        public Person()
        { }
    }

More Attribute Types

Sometimes we need more flexibility with out attribute types in CRM. An example is the Picklist attribute, we may need to map this to a Enum for example. Given the follwoing Enum:

    public enum HardDriveType
    {
        Fibre, IDE, SAS, SCSI, Other
    }

We could map our picklist several ways:

 #region Picklists

        [XrmFieldMapping("srv_harddrivetype", CrmType = AttributeType.Picklist, IsReadOnly = true)]
        public string HardDriveType { get; private set; }

        [XrmFieldMapping("srv_harddrivetype", CrmType = AttributeType.Picklist)]
        public int HardDriveType { get; set; }

        [XrmFieldMapping("srv_harddrivetype", CrmType = AttributeType.Picklist)]
        public HardDriveType HardDriveType { get; set; }

        [XrmFieldMapping("srv_harddrivetype", CrmType = AttributeType.Picklist)]
        public XrmPicklistInfo HardDriveType { get; set; }

#endregion

Usage

We can simply create/retrieve/update/delete our objects using the extension methods provided.
    QueryExpression qe = new QueryExpression("contact") { ColumnSet = new AllColumns() };
    qe.Criteria.AddCondition("firstname", ConditionOperator.Equal, "James");

    try
    {
        //RetrieveMultiple and retrieve as a typeof<Person>
        IEnumerable<Person> people = crmService.RetrieveMultiple<Person>(qe);

        //Output our results
        foreach (var person in people)
            Console.WriteLine("{0} {1} - {2}", person.FirstName, person.LastName, person.Account.DisplayName);

        //Save a new IXrmEntity, save will perform a create if the entity is new and an update if it's an existing entity.
        Guid personId = crmService.Save(new Person()
        {
            FirstName = "Kurt",
            LastName = "Gooding"
        });

        //Retrieve the newly created Person
        Person myPerson = crmService.Retrieve<Person>(personId);

        myPerson.FirstName= "David";

        crmService.Update(myPerson);

        //Delete the newly created person
        crmService.Delete(myPerson);
    }
    catch (SoapException sex)
    {
        Console.WriteLine(sex.Detail.InnerText);
    }
    finally
    {
        Console.ReadLine();
    }

Extension Methods


    #region Crm Functions
    
    CrmService crmService = Program.GetService();
    
    Guid id = new Guid("{ED884DC9-49E4-4a97-AFC9-330B84C18114}");

    //Assign an enitity to a user, if there is no UserId sepecified 
    //it will assign it to the logged in user. 
    crmService.Assign("contact", id);

    //Retrieve contact, if no columns are passed all columns are retrieved
    contact myContact = crmService.Retrieve<contact>(id, "firstname", "emailaddress1");

    //Retrieve a DynamicEntity
    DynamicEntity dynEntity = crmService.RetrieveDynamic("contact", id, "firstname", "emailaddress1");

    //Try and retrieve an entity with an id
    //This will swallow the exception only if the record is not found.
    lead myLead = crmService.TryRetrieve<lead>(id);

    //WhoAmI Request
    WhoAmIResponse whoAmI = crmService.WhoAmI();

    //Current User Id
    Guid loggedInUser = crmService.GetCurrentUserId();

    //Convert a CRM entity to a dynamic entity
    DynamicEntity dynContact = myContact.AsDynamic();
   
    //Add a property
    dynContact.SetValue<CrmBoolean>("donotemail", new CrmBoolean(true));

    //Convert back to a business entity
    contact contact = dynContact.AsEntity<contact>();

    #endregion

SQL Helpers

These extension methods make querying CRM FilteredViews and Tables easier. They allow you to pass an Id of the user you wish to impersonate. There is also an extension method AsCrmEnumerable<TEntity>() that will convert a IDataReader to an enumerable sequence of a specified CRM type. Example:


    #region SqlHelpers

    CrmService service = Program.GetService();

    Guid impersonateId = service.GetCurrentUserId();

    const string connStr = "Data Source=server; Initial Catalog=Org_MSCRM; Integrated Security=SSPI";
    const string sqlCmd = "SELECT TOP 500 * FROM FilteredContact WHERE statecode = 0";

    using (SqlConnection conn = new SqlConnection(connStr))
    {
        using (SqlCommand cmdContacts = new SqlCommand(sqlCmd, conn))
        {
            conn.Open();

            var contacts = cmdContacts
                //ExecuteReader, ExecuteScalar, ExecuteNonQuery all have an overload for
                //crm impersonation, this helps querying filtered views.
                .ExecuteReader(impersonateId)
                //When using a datareader the ToCrmEntityList<T> method will create an
                //IEnumerable sequence of CRM Entities given a type.
                .AsCrmEnumerable<contact>();


            contacts.ForEach(c =>
            {
                Console.Write("Contact Name: {0} - Id: {1}", c.fullname, c.contactid.Value);
            });

            conn.Close();
        }

    }

    #endregion
More documentation to come.

Last edited Feb 22, 2010 at 10:19 PM by kgooding, version 11

Comments

No comments yet.