/// <summary>
        /// Add new device profile.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
		public GXDeviceProfilesUpdateResponse Post(GXDeviceProfilesUpdateRequest request)
		{
            List<GXEventsItem> events = new List<GXEventsItem>();
            GXAmiDeviceProfile DeviceProfiles = null;
            lock (Db)
            {
                using (var trans = Db.OpenTransaction(IsolationLevel.ReadCommitted))
                {
                    string filename = Path.GetTempFileName();
                    using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        BinaryWriter w = new BinaryWriter(stream);
                        w.Write(request.Data);
                    }
                    string pathToDll = this.GetType().Assembly.CodeBase;
                    // Create an Application Domain:
                    AppDomainSetup domainSetup = new AppDomainSetup { PrivateBinPath = pathToDll };
                    System.AppDomain td = null;
                    string dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + Path.DirectorySeparatorChar);
                    //Try to load device template and unload assmbly.                          
                    try
                    {
                        td = AppDomain.CreateDomain("TestDomain", null, domainSetup);
                        GXProxyClass pc = (GXProxyClass)(td.CreateInstanceFromAndUnwrap(pathToDll, typeof(GXProxyClass).FullName));
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                        byte[] data;
                        string addInType, assemblyName;
                        List<object[]> items = pc.Import(filename, dir, out data, out assemblyName, out addInType);
                        ulong DeviceProfileID = 0;
                        ulong categoryTemplateID = 0;
                        ulong propertyTemplateID = 0;
                        ulong tableTemplateID = 0;
                        int version = 0;
                        foreach (object[] it in items)
                        {
                            if (it[1] is GXAmiDeviceProfile)
                            {
                                DeviceProfiles = it[1] as GXAmiDeviceProfile;
                                events.Add(new GXEventsItem(ActionTargets.DeviceProfile, Actions.Add, DeviceProfiles));
                                //Find new version number for the template.
                                foreach (GXAmiDeviceProfile dt in Db.Select<GXAmiDeviceProfile>(q => q.Guid == DeviceProfiles.Guid))
                                {
                                    if (dt.ProfileVersion > version)
                                    {
                                        version = dt.ProfileVersion;
                                    }
                                }
                                ++version;
                                DeviceProfiles.ProtocolAddInType = addInType;
                                DeviceProfiles.ProtocolAssembly = assemblyName;
                                DeviceProfiles.ProfileVersion = version;
                            }
                            else if (it[1] is GXAmiCategoryTemplate)
                            {
                                tableTemplateID = 0;
                                (it[1] as GXAmiCategoryTemplate).DeviceID = DeviceProfileID;
                                (it[1] as GXAmiCategoryTemplate).Id += DeviceProfileID << 16;
                                (it[1] as GXAmiCategoryTemplate).TemplateVersion = version;
                            }
                            else if (it[1] is GXAmiDataTableTemplate)
                            {
                                categoryTemplateID = 0;
                                (it[1] as GXAmiDataTableTemplate).DeviceID = DeviceProfileID;
                                (it[1] as GXAmiDataTableTemplate).Id += DeviceProfileID << 16;
                                (it[1] as GXAmiDataTableTemplate).TemplateVersion = version;
                            }
                            else if (it[1] is GXAmiPropertyTemplate)
                            {
                                (it[1] as GXAmiPropertyTemplate).DeviceID = DeviceProfileID;
                                (it[1] as GXAmiPropertyTemplate).TemplateVersion = version;
                                if (categoryTemplateID != 0)
                                {
                                    (it[1] as GXAmiPropertyTemplate).ParentID = categoryTemplateID;
                                }
                                else if (tableTemplateID != 0)
                                {
                                    (it[1] as GXAmiPropertyTemplate).ParentID = tableTemplateID;
                                }
                                else
                                {
                                    throw new ArgumentOutOfRangeException("Parent ID.");
                                }
                                (it[1] as GXAmiPropertyTemplate).Id += DeviceProfileID << 16;
                            }
                            else if (it[1] is GXAmiParameterTemplate)
                            {
                                (it[1] as GXAmiParameterTemplate).DeviceID = DeviceProfileID;
                                (it[1] as GXAmiParameterTemplate).TemplateVersion = version;
                                if (it[0] is GXAmiDeviceProfile)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = DeviceProfileID << 16;
                                }
                                else if (it[0] is GXAmiCategoryTemplate)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = categoryTemplateID;
                                }
                                else if (it[0] is GXAmiDataTableTemplate)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = tableTemplateID;
                                }
                                else if (it[0] is GXAmiPropertyTemplate)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = propertyTemplateID;
                                }                                
                            }
                            Db.Insert(it[1]);
                            if (it[1] is GXAmiDeviceProfile)
                            {
#if !SS4
                                ulong value = (ulong)Db.GetLastInsertId();
#else
                                ulong value = (ulong)Db.LastInsertId();
#endif                                                                   
                                (it[1] as GXAmiDeviceProfile).Id = value;
                                DeviceProfileID = value;
                                //Update allowed media types.
                                foreach (GXAmiMediaType mt in (it[1] as GXAmiDeviceProfile).AllowedMediaTypes)
                                {
                                    mt.DeviceProfileId = DeviceProfileID;
                                    Db.Insert(mt);
                                }
                            }
                            else if (it[1] is GXAmiCategoryTemplate)
                            {
                                categoryTemplateID = (it[1] as GXAmiCategoryTemplate).Id;
                            }
                            else if (it[1] is GXAmiDataTableTemplate)
                            {
                                tableTemplateID = (it[1] as GXAmiDataTableTemplate).Id;
                            }
                            else if (it[1] is GXAmiPropertyTemplate)
                            {
                                propertyTemplateID = (it[1] as GXAmiPropertyTemplate).Id;
                                if ((it[1] as GXAmiPropertyTemplate).Values != null && (it[1] as GXAmiPropertyTemplate).Values.Length != 0)
                                {
#if !SS4
                                    ulong value = (ulong)Db.GetLastInsertId();
#else
                                    ulong value = (ulong)Db.LastInsertId();
#endif
                                    foreach (GXAmiValueItem vi in (it[1] as GXAmiPropertyTemplate).Values)
                                    {
                                        vi.ProfileId = DeviceProfileID;
                                        vi.PropertyId = value;
                                        Db.Insert(vi);
                                    }
                                }
                            }
                            else if (it[1] is GXAmiParameterTemplate)
                            {
                                if ((it[1] as GXAmiParameterTemplate).Values != null && (it[1] as GXAmiParameterTemplate).Values.Length != 0)
                                {
#if !SS4
                                    ulong value = (ulong)Db.GetLastInsertId();
#else
                                ulong value = (ulong)Db.LastInsertId();
#endif
                                    foreach (GXAmiValueItem vi in (it[1] as GXAmiParameterTemplate).Values)
                                    {
                                        vi.ProfileId = DeviceProfileID;
                                        vi.ParameterId = value;
                                        Db.Insert(vi);
                                    }
                                }
                            }
                        }
                        //Save device template to data blocks.
                        foreach (GXAmiDeviceProfilesDataBlock it in SplitDataToPackets(DeviceProfileID, filename))
                        {
                            Db.Insert(it);
                        }
                        foreach (GXAmiDeviceProfilesDataBlock it in SplitDataToPackets(DeviceProfileID, filename))
                        {
                            Db.Insert(it);
                        }
                        if (request.UserGroups != null)
                        {
                            foreach (long ugId in request.UserGroups)
                            {
                                GXAmiUserGroupDeviceProfile it = new GXAmiUserGroupDeviceProfile();
                                it.DeviceProfileID = DeviceProfileID;
                                it.UserGroupID = ugId;
                                Db.Insert(it);
                            }
                        }
                    }
                    finally
                    {
                        // Unload the application domain:
                        if (td != null)
                        {
                            System.AppDomain.Unload(td);
                        }
                        if (dir != null)
                        {
                            try
                            {
                                Directory.Delete(dir, true);
                            }
                            catch
                            {
                                //It's OK if this fails.
                            }
                        }
                    }
                    trans.Commit();
                }
            }
            AppHost host = this.ResolveService<AppHost>();
            host.SetEvents(Db, this.Request, 0, events);
            return new GXDeviceProfilesUpdateResponse(request.UserGroups, DeviceProfiles);
        }
        /// <summary>
        /// Add new device profile.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GXDeviceProfilesUpdateResponse Post(GXDeviceProfilesUpdateRequest request)
        {
            List <GXEventsItem> events         = new List <GXEventsItem>();
            GXAmiDeviceProfile  DeviceProfiles = null;

            lock (Db)
            {
                using (var trans = Db.OpenTransaction(IsolationLevel.ReadCommitted))
                {
                    string filename = Path.GetTempFileName();
                    using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        BinaryWriter w = new BinaryWriter(stream);
                        w.Write(request.Data);
                    }
                    string pathToDll = this.GetType().Assembly.CodeBase;
                    // Create an Application Domain:
                    AppDomainSetup domainSetup = new AppDomainSetup {
                        PrivateBinPath = pathToDll
                    };
                    System.AppDomain td  = null;
                    string           dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + Path.DirectorySeparatorChar);
                    //Try to load device template and unload assmbly.
                    try
                    {
                        td = AppDomain.CreateDomain("TestDomain", null, domainSetup);
                        GXProxyClass pc = (GXProxyClass)(td.CreateInstanceFromAndUnwrap(pathToDll, typeof(GXProxyClass).FullName));
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                        byte[]          data;
                        string          addInType, assemblyName;
                        List <object[]> items              = pc.Import(filename, dir, out data, out assemblyName, out addInType);
                        ulong           DeviceProfileID    = 0;
                        ulong           categoryTemplateID = 0;
                        ulong           propertyTemplateID = 0;
                        ulong           tableTemplateID    = 0;
                        int             version            = 0;
                        foreach (object[] it in items)
                        {
                            if (it[1] is GXAmiDeviceProfile)
                            {
                                DeviceProfiles = it[1] as GXAmiDeviceProfile;
                                events.Add(new GXEventsItem(ActionTargets.DeviceProfile, Actions.Add, DeviceProfiles));
                                //Find new version number for the template.
                                foreach (GXAmiDeviceProfile dt in Db.Select <GXAmiDeviceProfile>(q => q.Guid == DeviceProfiles.Guid))
                                {
                                    if (dt.ProfileVersion > version)
                                    {
                                        version = dt.ProfileVersion;
                                    }
                                }
                                ++version;
                                DeviceProfiles.ProtocolAddInType = addInType;
                                DeviceProfiles.ProtocolAssembly  = assemblyName;
                                DeviceProfiles.ProfileVersion    = version;
                            }
                            else if (it[1] is GXAmiCategoryTemplate)
                            {
                                tableTemplateID = 0;
                                (it[1] as GXAmiCategoryTemplate).DeviceID        = DeviceProfileID;
                                (it[1] as GXAmiCategoryTemplate).Id             += DeviceProfileID << 16;
                                (it[1] as GXAmiCategoryTemplate).TemplateVersion = version;
                            }
                            else if (it[1] is GXAmiDataTableTemplate)
                            {
                                categoryTemplateID = 0;
                                (it[1] as GXAmiDataTableTemplate).DeviceID        = DeviceProfileID;
                                (it[1] as GXAmiDataTableTemplate).Id             += DeviceProfileID << 16;
                                (it[1] as GXAmiDataTableTemplate).TemplateVersion = version;
                            }
                            else if (it[1] is GXAmiPropertyTemplate)
                            {
                                (it[1] as GXAmiPropertyTemplate).DeviceID        = DeviceProfileID;
                                (it[1] as GXAmiPropertyTemplate).TemplateVersion = version;
                                if (categoryTemplateID != 0)
                                {
                                    (it[1] as GXAmiPropertyTemplate).ParentID = categoryTemplateID;
                                }
                                else if (tableTemplateID != 0)
                                {
                                    (it[1] as GXAmiPropertyTemplate).ParentID = tableTemplateID;
                                }
                                else
                                {
                                    throw new ArgumentOutOfRangeException("Parent ID.");
                                }
                                (it[1] as GXAmiPropertyTemplate).Id += DeviceProfileID << 16;
                            }
                            else if (it[1] is GXAmiParameterTemplate)
                            {
                                (it[1] as GXAmiParameterTemplate).DeviceID        = DeviceProfileID;
                                (it[1] as GXAmiParameterTemplate).TemplateVersion = version;
                                if (it[0] is GXAmiDeviceProfile)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = DeviceProfileID << 16;
                                }
                                else if (it[0] is GXAmiCategoryTemplate)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = categoryTemplateID;
                                }
                                else if (it[0] is GXAmiDataTableTemplate)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = tableTemplateID;
                                }
                                else if (it[0] is GXAmiPropertyTemplate)
                                {
                                    (it[1] as GXAmiParameterTemplate).ParentID = propertyTemplateID;
                                }
                            }
                            Db.Insert(it[1]);
                            if (it[1] is GXAmiDeviceProfile)
                            {
#if !SS4
                                ulong value = (ulong)Db.GetLastInsertId();
#else
                                ulong value = (ulong)Db.LastInsertId();
#endif
                                (it[1] as GXAmiDeviceProfile).Id = value;
                                DeviceProfileID = value;
                                //Update allowed media types.
                                foreach (GXAmiMediaType mt in (it[1] as GXAmiDeviceProfile).AllowedMediaTypes)
                                {
                                    mt.DeviceProfileId = DeviceProfileID;
                                    Db.Insert(mt);
                                }
                            }
                            else if (it[1] is GXAmiCategoryTemplate)
                            {
                                categoryTemplateID = (it[1] as GXAmiCategoryTemplate).Id;
                            }
                            else if (it[1] is GXAmiDataTableTemplate)
                            {
                                tableTemplateID = (it[1] as GXAmiDataTableTemplate).Id;
                            }
                            else if (it[1] is GXAmiPropertyTemplate)
                            {
                                propertyTemplateID = (it[1] as GXAmiPropertyTemplate).Id;
                                if ((it[1] as GXAmiPropertyTemplate).Values != null && (it[1] as GXAmiPropertyTemplate).Values.Length != 0)
                                {
#if !SS4
                                    ulong value = (ulong)Db.GetLastInsertId();
#else
                                    ulong value = (ulong)Db.LastInsertId();
#endif
                                    foreach (GXAmiValueItem vi in (it[1] as GXAmiPropertyTemplate).Values)
                                    {
                                        vi.ProfileId  = DeviceProfileID;
                                        vi.PropertyId = value;
                                        Db.Insert(vi);
                                    }
                                }
                            }
                            else if (it[1] is GXAmiParameterTemplate)
                            {
                                if ((it[1] as GXAmiParameterTemplate).Values != null && (it[1] as GXAmiParameterTemplate).Values.Length != 0)
                                {
#if !SS4
                                    ulong value = (ulong)Db.GetLastInsertId();
#else
                                    ulong value = (ulong)Db.LastInsertId();
#endif
                                    foreach (GXAmiValueItem vi in (it[1] as GXAmiParameterTemplate).Values)
                                    {
                                        vi.ProfileId   = DeviceProfileID;
                                        vi.ParameterId = value;
                                        Db.Insert(vi);
                                    }
                                }
                            }
                        }
                        //Save device template to data blocks.
                        foreach (GXAmiDeviceProfilesDataBlock it in SplitDataToPackets(DeviceProfileID, filename))
                        {
                            Db.Insert(it);
                        }
                        foreach (GXAmiDeviceProfilesDataBlock it in SplitDataToPackets(DeviceProfileID, filename))
                        {
                            Db.Insert(it);
                        }
                        if (request.UserGroups != null)
                        {
                            foreach (long ugId in request.UserGroups)
                            {
                                GXAmiUserGroupDeviceProfile it = new GXAmiUserGroupDeviceProfile();
                                it.DeviceProfileID = DeviceProfileID;
                                it.UserGroupID     = ugId;
                                Db.Insert(it);
                            }
                        }
                    }
                    finally
                    {
                        // Unload the application domain:
                        if (td != null)
                        {
                            System.AppDomain.Unload(td);
                        }
                        if (dir != null)
                        {
                            try
                            {
                                Directory.Delete(dir, true);
                            }
                            catch
                            {
                                //It's OK if this fails.
                            }
                        }
                    }
                    trans.Commit();
                }
            }
            AppHost host = this.ResolveService <AppHost>();
            host.SetEvents(Db, this.Request, 0, events);
            return(new GXDeviceProfilesUpdateResponse(request.UserGroups, DeviceProfiles));
        }