Create User Entity Data Source Provider
- Last UpdatedJun 10, 2024
- 13 minute read
Using this API a custom User Entity Data Source Provider can be created.
Note: The Repository for which you are going to create the User Entity Data Source Provider, should have Authentication provider as "AVEVA Work Tasks List".
-
Create a table named SqlUsers
The custom entity provider fetches the user information from a table called SqlUsers.
Script to create this table is provided below:
GO
/****** Object: Table [dbo].[SqlUsers] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SqlUsers](
[UserId] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [DF_SqlUsers_Id] DEFAULT (newid()),
[Name] [nvarchar](100) NULL,
[Role] [nvarchar](200) NULL,
[Email] [nvarchar](75) NULL,
[Password] [nchar](10) NULL,
CONSTRAINT [PK_SqlUsers_1] PRIMARY KEY CLUSTERED
(
[UserId] ASC
) WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
-
Insert default users to SqlUsers Table
Script to insert default users to SqlUsers Table:
INSERT INTO [dbo].[SqlUsers]
([Name]
,[Role]
,[Email]
,[Password])
VALUES
('Michelle','Admin','michelle@skelta.com','michelle'),
('kevin','Developer','kevin@skelta.com','kevin'),
('john','Developer','john@skelta.com','john'),
('Elaine','Product Manager','elaine@skelta.com','elaine')
GO
-
Create a dll named CustomUserEntityDataSourceProvider
PROCEDURE
DLL REFERENCE
Workflow.NET.NET2
System.Transactions.dll
System.Web.dll
NAMESPACE USED
System
System.Collections.Generic
System.Text
System.Xml
System.Xml.XPath
System.Transactions
System.Data
Workflow.NET
Workflow.NET.Interfaces
Skelta.Entity
API INFORMATION
The User Entity Data Source Provider should
Inherit Skelta.Entity.DataSourceProviderBase class
or
Implement Skelta.Entity.IEntityDataSourceProvider, Skelta.Core.ISkeltaAddInProvider
Implement interface Skelta.Entity.UserEntityProvider.IUserEntityDataSourceProvider
Implement interface Skelta.Entity.IEntityAdminDataSourceProvide.
Skelta.Entity.DataSourceProviderBase: Base class used by the default providers, this class implements the interfaces Skelta.Entity.IEntityDataSourceProvider, Skelta.Core.ISkeltaAddInProvider. All the methods in this class are declared as virtual. The implementers should ideally implement the interfaces implemented by the base class directly. The base class is used in the sample trying to make it easier for the implementer with some of the methods already implemented with default functionality. The method which needs to be mandatorily overridden throws exception if relied on the base class. This class exposes methods for initializing the provider, fetching user information & querying users based on filters.
Skelta.Entity.UserEntityProvider.IUserEntityDataSourceProvider: Gets called during EnterpriseConsole authentication from the Log on page. This interface provides methods which gives username & password entered in the login page of EnterpriseConsole. All the user authentication code must be implemented in these methods.
Skelta.Entity.IEntityAdminDataSourceProvider: Required for setting the default administrator for a Repository. This administrator will have complete rights on the EC site. This administrator will be responsible for setting security and adding users to EC.
SAMPLE CODE:
namespace CustomUserEntityDataSourceProvider
{
/// <summary>
/// Custom entity data source provider which queries sql database table/view returning user information.
/// </summary>
public class UserEntityDataSourceProvider : DataSourceProviderBase, Skelta.Entity.UserEntityProvider.IUserEntityDataSourceProvider,
Skelta.Entity.IEntityAdminDataSourceProvider
{
private string sConnectionString;
private string sDataSourceType;
private string sSourceTable;
private string sCols = "";
private Log log = null;
private string loginProperty = "";
public UserEntityDataSourceProvider() { }
/// <summary>
/// Gets called while provider is initialized.
/// </summary>
/// <param name="settings">Definition XML configured for SKEntityDataSourceProvider table.</param>
public override void Initialize(string settings)
{
log = new Log();
log.FileName = "CustomUserEntityDataSourceProvider.cs";
XmlDocument doc = new XmlDocument();
try
{
doc.LoadXml(settings);
// Get the Connection String from the definition xml file.
XmlNode DsConnNode = doc.GetElementsByTagName("datasource").Item(0);
sConnectionString = DsConnNode.InnerText;
sDataSourceType = "sql server";
sSourceTable = doc.GetElementsByTagName("SourceTable").Item(0).InnerText;
}
catch (Exception exp)
{
log.LogError(exp, "Could not read the xml data while initializing the provider");
throw;
}
try
{
if (doc.GetElementsByTagName("loginproperty") != null)
{
XmlNode qxn = doc.GetElementsByTagName("loginproperty").Item(0);
loginProperty = qxn.InnerText;
}
}
catch (Exception ex)
{
log.LogError(ex, "Could not get loginproperty column set.");
throw;
}
}
/// <summary>
/// Called when delayed initialization on a resource property is required.
/// For example if there are 2 providers and the initial property collection for the resource
/// has a property which is empty and if this property is requested a delayed initialization is
/// triggered on the provider based on the mapping fields configured.
/// </summary>
/// <param name="filter">Filter which is internally built based on the mapping fields configured.</param>
/// <param name="dataparams">Parameters used in the filter.</param>
/// <returns>Entity item with the delayed initialization property value.</returns>
public override EntityItem GetEntityItem(string filter, object[] dataParams)
{
if(string.IsNullOrEmpty(sCols))
BuildPropertyColumn();
List<IDataParameter> dParam = new List<IDataParameter>();
string sql = string.Empty;
using (IDataHandler dbHandler = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType))
{
sql = "SELECT " + sCols + " FROM " + sSourceTable + " WHERE " + filter;
try
{
foreach (object[] values in dataParams)
{
dParam.Add(dbHandler.GetParameter(values[0].ToString(), values[1]));
}
return GetEntityItem(sql, dParam.ToArray());
}
catch (Exception exp)
{
log.LogError(exp, "Could not fetch entity item with filter (" + filter + ").");
throw;
}
}
}
/// <summary>
/// Called when actor object is created or any resource details are requested.
/// </summary>
/// <param name="entityItemId">Guid of the resource based on the current sample.</param>
/// <returns>User Entity Details.</returns>
public override EntityItem GetEntityItem(object entityItemId)
{
if (string.IsNullOrEmpty(sCols))
BuildPropertyColumn();
string sql = string.Empty;
IDataParameter dParam = null;
using (IDataHandler dbHandler = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType))
{
try
{
sql = "SELECT " + sCols + " FROM " + sSourceTable + " WHERE " + EntityItemProperties.Identifier.PropertyName + " = @resourceId";
dParam = dbHandler.GetParameter("@resourceId", entityItemId);
return GetEntityItem(sql, dParam);
}
catch (Exception exp)
{
log.LogError(exp, "Could not fetch entity item for entity item id (" + entityItemId + ").");
throw;
}
}
}
EntityItem GetEntityItem(string filter, params IDataParameter[] dataparams)
{
IDataReader idr = null;
EntityItem res;
Workflow.NET.Interfaces.IDataHandler ConnectionWrapper = null;
using (ConnectionWrapper = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType))
{
idr = ConnectionWrapper.ExecuteReader(filter, dataparams);
//Create a empty EntityItem object
res = new EntityItem();
res.Properties = EntityItemProperties.CreateDeepClone();
string fieldname;
EntityItemProperty rp;
int loopcount = 0;
while (idr.Read())
{
//For every record, update the properties values
for (int i = 0; i < idr.FieldCount; i++)
{
fieldname = idr.GetName(i);
if (res.Properties.ContainsKey(fieldname))
{
rp = ((EntityItemProperty)res.Properties[fieldname]);
if (!rp.Values.Contains(idr.GetValue(i)) && idr.GetValue(i) != System.DBNull.Value && idr.GetValue(i).ToString() != "") //Add all unique values of a given field in Values collection
rp.Values.Add(idr.GetValue(i));
}
else
{ //if( loopcount==0 )
log.LogWarning("Field " + fieldname + " not found in EntityItem Properties");
}
}
loopcount++;
}
idr.Close();
idr.Dispose();
}
return res;
}
/// <summary>
/// Called when an filter is executed in Runtime, for example when Human activity is executed.
/// This method also gets called when user look search is performed
/// </summary>
/// <param name="filter">Filter for querying the resource.</param>
/// <param name="query"></param>
/// <param name="FullyProcessedQuery"></param>
/// <param name="Params"></param>
/// <returns></returns>
public override object[] QueryEntityItem(string filter, string query, string FullyProcessedQuery, object[] Params)
{
// When QueryEntityItem is called from Runtime (Engine),
//there is an option to get the executing context details using GetEntityExecutionContext method.
Skelta.Entity.EntityExecutionContextInfo entityExecutionContextInfo =
Skelta.Entity.EntityExecutionContext.GetEntityExecutionContext();
//if (entityExecutionContextInfo != null)
//{
//entityExecutionContextInfo.ApplicationName;
//entityExecutionContextInfo.WorkflowName;
//entityExecutionContextInfo.ExecutionId
//}
IDataReader idr = null;
Workflow.NET.Interfaces.IDataHandler ConnectionWrapper = null;
try
{
using (ConnectionWrapper = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType))
{
string sql = "SELECT DISTINCT " + EntityItemProperties.Identifier.PropertyName + " FROM " + sSourceTable;
System.Collections.ArrayList EntityItems = new System.Collections.ArrayList();
if (FullyProcessedQuery != null && FullyProcessedQuery.Trim().Length > 0)
{
sql += " WHERE " + FullyProcessedQuery;
}
else
{
log.LogWarning("EntityItem filter is emtpy.");
return EntityItems.ToArray();
}
System.Collections.ArrayList alParams = new System.Collections.ArrayList();
foreach (object Param in Params)
{
object[] obj = (object[])Param;
alParams.Add(ConnectionWrapper.GetParameter((string)obj[0], obj[1]));
}
IDataParameter[] Parameters = (IDataParameter[])alParams.ToArray(typeof(IDataParameter));
idr = ConnectionWrapper.ExecuteReader(sql, Parameters);
while (idr.Read())
{
EntityItems.Add(idr.GetValue(0));
}
idr.Close();
idr.Dispose();
return EntityItems.ToArray();
}
}
catch (Exception exp)
{
if (entityExecutionContextInfo != null)
log.LogError(exp, "Could not fetch entity item while querying entity item, filter(" + filter + ").", entityExecutionContextInfo.ApplicationName, entityExecutionContextInfo.WorkflowName, entityExecutionContextInfo.ExecutionId);
else
log.LogError(exp, "Could not fetch entity item while querying entity item, filter(" + filter + ").");
throw;
}
}
void BuildPropertyColumn()
{
if (string.IsNullOrEmpty(sCols))
{
foreach (EntityItemProperty prop in EntityItemProperties)
{
sCols += (sCols == "" ? "" : ",") + prop.PropertyName;
}
}
}
/// <summary>
/// Creates a clone of the user entity provider.
/// </summary>
/// <returns></returns>
public override IEntityDataSourceProvider Clone()
{
UserEntityDataSourceProvider customProvider = new UserEntityDataSourceProvider();
customProvider.sCols = this.sCols;
customProvider.Name = this.Name;
customProvider.sConnectionString = this.sConnectionString;
customProvider.sDataSourceType = this.sDataSourceType;
customProvider.sSourceTable = this.sSourceTable;
EntityItemPropertiesCollection entityItems = this.EntityItemProperties.CreateDeepClone();
foreach (EntityItemProperty eProp in entityItems)
{
customProvider.EntityItemProperties.Add(eProp.PropertyName, eProp);
}
foreach (string key in this.DataSourceMappingFields.Keys)
{
customProvider.DataSourceMappingFields.Add(key, this.DataSourceMappingFields[key]);
}
foreach (string key in this.DataSourceProperties.Keys)
{
customProvider.DataSourceProperties.Add(key, this.DataSourceProperties[key]);
}
foreach (string key in this.RuleParts.Keys)
{
customProvider.RuleParts.Add(key, this.RuleParts[key]);
}
customProvider.IsPrimaryDataSource = this.IsPrimaryDataSource;
customProvider.DataSourceType = this.DataSourceType;
customProvider.loginProperty = this.loginProperty;
customProvider.Name = this.Name;
customProvider.CurrentEntity = this.CurrentEntity;
customProvider.DisplayName = this.DisplayName;
customProvider.RepositoryName = this.RepositoryName;
customProvider.IsAuthenticationSource = this.IsAuthenticationSource;
customProvider.ProviderPrefix = this.ProviderPrefix;
return customProvider;
}
/// <summary>
/// Converts to provider specific identifier type;
/// </summary>
/// <param name="identifierId">real entity id converted as string.</param>
/// <returns>Id which is provider specific type converted.</returns>
public override object ConvertToIdentifierType(string identifierId)
{
switch (EntityItemProperties.Identifier.PropertyType)
{
case "string": return identifierId;
case "int": return int.Parse(identifierId);
case "guid": return new Guid(identifierId);
}
return null;
}
/// <summary>
/// Return the unique identifier for the user. The default return value is user name itself.
/// The actual unique identifier for the user could be different from the property used for login. For the sample though the unique identifier is guid we have provided email as the login property for ease of use.
/// </summary>
/// <param name="userName">Value entered in the login page against user name field.</param>
/// <param name="password">Password entered in the login page against password field.</param>
/// <returns>Unique identifier value. Return value type is object as the identifier type could be guid, int or string.</returns>
public override object GetUniqueIdentifier(string userName, string password)
{
if (string.IsNullOrEmpty(loginProperty))
return userName;
string passwordColumn = GetPasswordColumnName();
Workflow.NET.Interfaces.IDataHandler ConnectionWrapper = null;
string sql = "";
IDataParameter param1 = null;
IDataParameter param2 = null;
IDataReader idr = null;
try
{
ConnectionWrapper = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType);
sql = "SELECT * FROM " + sSourceTable + " WHERE " + loginProperty + "=@resourceId AND " + passwordColumn + "=@password";
param1 = ConnectionWrapper.GetParameter("@resourceId", userName);
param2 = ConnectionWrapper.GetParameter("@password", password);
idr = ConnectionWrapper.ExecuteReader(sql, param1, param2);
if (idr.Read())
return idr[EntityItemProperties.Identifier.PropertyName];
else
throw new System.Exception("Unable to get unique identifier from property (" + loginProperty + "), query(" + sql + ")");
}
catch (Exception e)
{
log.LogError(e, "Could not get unique identifier for user (" + userName + ")");
throw;
}
finally
{
if (idr != null)
idr.Close();
if (ConnectionWrapper != null)
ConnectionWrapper.Dispose();
}
}
//Returns the column name from property collection with purpose set as "password"
string GetPasswordColumnName()
{
foreach (EntityItemProperty eProp in EntityItemProperties)
{
if (!string.IsNullOrEmpty(eProp.Purpose) &&
eProp.Purpose.ToLowerInvariant() == "password")
return eProp.PropertyName;
}
return "";
}
#region IUserEntityDataSourceProvider Members
/// <summary>
/// Currently this method call is not used in any of the default providers.
/// It was added to provide an option in future release to perform login for a provider
/// based on different authentication methods available in IIS instead of performing a validation
/// based on user name & password
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
bool Skelta.Entity.UserEntityProvider.IUserEntityDataSourceProvider.ValidateIISUser(System.Web.HttpContext httpContext)
{
return false;
}
/// <summary>
/// Called when submit button event of login page is fired from EnterpriseConsole.
/// </summary>
/// <param name="userName">Value entered in the login page against user name field.</param>
/// <param name="password">Password entered in the login page against password field.</param>
/// <returns>true if user credentials are valid else false.</returns>
bool Skelta.Entity.UserEntityProvider.IUserEntityDataSourceProvider.ValidateUser(string username, string password)
{
string passwordColumn = GetPasswordColumnName();
string identifierColumn = "";
if (string.IsNullOrEmpty(loginProperty))
identifierColumn = EntityItemProperties.Identifier.PropertyName;
else
identifierColumn = loginProperty;
if (string.IsNullOrEmpty(passwordColumn))
return false;
else
{
Workflow.NET.Interfaces.IDataHandler ConnectionWrapper = null;
string sql = "";
IDataParameter param1 = null;
IDataParameter param2 = null;
IDataReader idr = null;
using (ConnectionWrapper = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType))
{
try
{
sql = "Select * From " + sSourceTable + " WHERE " + identifierColumn + "=@resourceId AND " + passwordColumn + "=@password";
param1 = ConnectionWrapper.GetParameter("@resourceId", username);
param2 = ConnectionWrapper.GetParameter("@password", password);
idr = ConnectionWrapper.ExecuteReader(sql, param1, param2);
bool returnFlag = false;
if (idr.Read())
returnFlag = true;
idr.Close();
return returnFlag;
}
catch (Exception e)
{
log.LogError(e, "Could not validate user (" + username + ")");
//Need not throw the exception as the UI will display error message if return value is false.
}
}
return false;
}
}
#endregion
#region IEntityAdminDataSourceProvider Members
/// <summary>
/// Return admin users unique identifier value.
/// This administrator will have complete rights on the EC site.
/// This administrator will be responsible for setting security and adding users to EC
/// </summary>
/// <returns>Unique identifier value of administrator</returns>
public object[] GetAdministrator()
{
//For the sample we'll use the column named Role with value set as Admin.
Workflow.NET.Interfaces.IDataHandler ConnectionWrapper = null;
System.Collections.ArrayList EntityItems = new System.Collections.ArrayList();
try
{
ConnectionWrapper = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(sConnectionString, sDataSourceType);
string stradmin = "Admin";
string sql = "SELECT DISTINCT " + EntityItemProperties.Identifier.PropertyName + " FROM " + sSourceTable;
sql += " WHERE Role = '" + stradmin + "'";
System.Collections.ArrayList alParams = new System.Collections.ArrayList();
IDataParameter[] Parameters = (IDataParameter[])alParams.ToArray(typeof(IDataParameter));
IDataReader idr = ConnectionWrapper.ExecuteReader(sql, Parameters);
while (idr.Read())
{
EntityItems.Add(Workflow.NET.CommonFunctions.GetGuid(idr, EntityItemProperties.Identifier.PropertyName));
}
idr.Close();
idr.Dispose();
}
catch (Exception e)
{
log.LogError(e, "Could not get the administrator user information.");
throw;
}
finally
{
if (ConnectionWrapper != null)
ConnectionWrapper.Dispose();
}
return EntityItems.ToArray();
}
#endregion
}
}
-
Configure Custom User Entity Data Source Provider
Configuring custom user entity data source provider involves entries in three tables of the Repository
-
Table : SKAddInProviders , Object : Skelta.Core.AddInProvider
-
Table : SKEntity, Object : Skelta.Entity.Entity
-
Table : SKEntityDataSourceProvider, Object : Skelta.Entity.DataSourceProvider
-
Add the assembly information of the user entity custom provider created, in the SKAddInProviders table
Provider type must be "UserDSProvider" and name should be any unique name. The newly added provider name must be again updated in the SKEntityDataSourceProvider table.
Using API:
Skelta.Core.AddInProvider addInProvider = new Skelta.Core.AddInProvider(
new ApplicationObject("Sample Repository"));
addInProvider.Type = "UserDSProvider";
addInProvider.Name = "customsqlprovider";
#warning : Make sure to change the assembly path
addInProvider.Description = "Sample Custom User Entity Data Source Provider";
addInProvider.ClassName = "CustomUserEntityDataSourceProvider.UserEntityDataSourceProvider";
addInProvider.AssemblyNameWithAbsoluteOrRelativePath = @"M:\Michelle\CustomUserEntityDataSourceProvider\
CustomUserEntityDataSourceProvider\bin\Debug\CustomUserEntityDataSourceProvider.dll";
addInProvider.IsGacAssembly = false;
addInProvider.IsGlobal = true;
addInProvider.IsDefault = true; // The properties IsGacAssembly, IsGlobal, IsDefault is //not currently in use. The value used in sample should be used "as is"
addInProvider.Save();
Using Script:
INSERT INTO SKAddInProviders VALUES (newid(),'UserDSProvider','customsqlprovider',
'Sample Custom User Entity Data Source Provider ','CustomUserEntityDataSourceProvider.UserEntityDataSourceProvider',
'M:\Michelle\CustomUserEntityDataSourceProvider\CustomUserEntityDataSourceProvider\bin\Debug\CustomUserEntityDataSourceProvider.dll',null,0,1,1,getutcdate())
Note: Assembly path should be changed.
Verification:
The above code creates an entry in SKAddInProviders table with type as 'UserDSProvider'. The entry in Repository DB can be verified in database by running the query select * from SKAddInProviders Where Name='customsqlprovider'
|
Column Name |
Value |
|---|---|
|
ID |
Auto Generated |
|
Type |
UserDSProvider |
|
Name |
customsqlprovider |
|
Description |
Sample Custom User Entity Data Source Provider |
|
ClassName |
CustomUserEntityDataSourceProvider. UserEntityDataSourceProvider |
|
Assembly |
M:\Michelle\ CustomUserEntityDataSourceProvider\ CustomUserEntityDataSourceProvider\ bin\Debug \CustomUserEntityDataSourceProvider.dll |
|
IsGacAssembly |
False |
|
Isdefault |
True |
|
IsGlobal |
True |
|
DateTime |
Date time value |
-
Adding entry to SKEntity and SKEntityDataSourceProvider
-
Update the DefinitionXml column of SKEntity table with appropriate resource XML data for the newly created custom user entity provider that has been updated in the SKAddInProviders table.
-
Update the DefinitionXml column, Provider, Instance Name, Display Name for default entry of the List in SKEntityDataSourceProvider table with appropriate custom user entity data source provider entries.
-
Custom User Entity Data Source Provider Definition XML
<dataproviders>
<provider name="customsqlprovider" type="Custom Sql Provider">
<properties>
<property name="UserId" type="guid" purpose="identifier" />
<property name="Name" type="string" purpose="name"/>
<property name="Email" type="string" purpose="email"/>
<property name="Password" type="string" purpose="password"/>
</properties>
<datasource>server=localhost;database=SkeltaUsers;uid=sa;pwd= XXXX</datasource>
<SourceTable>SqlUsers</SourceTable>
<loginproperty>Email</loginproperty>
</provider>
</dataproviders>
-
"provider" node has attribute name value set as customsqlprovider as this should match the Name column entry in SKAddInProvider.
-
As described in earlier sections the purpose attributes identifier, name & email are mandatory.
-
Custom purpose named password is used to identify the column containing password info for authentication.
-
"datasource" node contains connection string information.
-
"SourceTable" node contains the table or view which contains user details.
-
"loginproperty" node provides information of the column which will be used as user name while logging in to Repository.
Custom Entity Definition XML
<entity type="user">
<properties>
<property name="UserId" type="string" purpose="identifier" />
<property name="Name" type="string" purpose="name"/>
<property name="Email" type="string" purpose="email"/>
</properties>
</entity>%%$#@@!!!*&
-
Contains properties which are mapped to user entity definition XML properties.
-
As described in earlier sections the purpose attributes identifier, name & email are mandatory.
Using API for steps 1 & 2:
Skelta.Core.ApplicationObject applicationObject = new Skelta.Core.ApplicationObject("Sample Repository");
Skelta.Entity.Entity entity = Skelta.Entity.Entity.GetEntity(applicationObject, "UserEntity");
string entityDefinitionXML = "<entity type=\"user\">";
entityDefinitionXML += "<properties>";
entityDefinitionXML += "<property name=\"UserId\" type=\"string\" purpose=\"identifier\" />";
entityDefinitionXML += "<property name=\"Name\" type=\"string\" purpose=\"name\"/>";
entityDefinitionXML += "<property name=\"Email\" type=\"string\" purpose=\"email\"/>";
entityDefinitionXML += "</properties>";
entityDefinitionXML += "</entity>%%$#@@!!!*&";
//Update default entity definition xml with matching xml for new custom user entity data source provider
entity.DefinitionXml = entityDefinitionXML;
entity.Save();
Skelta.Entity.DataSourceProviderCollection entityDataSourceProvider = null;
entityDataSourceProvider = new Skelta.Entity.DataSourceProviderCollection(applicationObject,entity.Id);
//Entity user xml need to be changed based on the custom User table
#warning : Make sure to change the connection string
string entityDataSourceProviderDefinitionXML = "<dataproviders>";
entityDataSourceProviderDefinitionXML += "<provider name=\"customsqlprovider\" type=\"Custom Sql Provider\">";
entityDataSourceProviderDefinitionXML += "<properties>";
entityDataSourceProviderDefinitionXML += "<property name=\"UserId\" type=\"guid\" purpose=\"identifier\"/>";
entityDataSourceProviderDefinitionXML += "<property name=\"Name\" type=\"string\" purpose=\"name\"/>";
entityDataSourceProviderDefinitionXML += "<property name=\"Email\" type=\"string\" purpose=\"email\"/>";
entityDataSourceProviderDefinitionXML += "<property name=\"Password\" type=\"string\" purpose=\"password\"/>";
entityDataSourceProviderDefinitionXML += "</properties>";
entityDataSourceProviderDefinitionXML += "<datasource>server=localhost;database=SkeltaUsers;uid=sa;pwd=XXXX</datasource>";
entityDataSourceProviderDefinitionXML += "<SourceTable>SqlUsers</SourceTable>";
entityDataSourceProviderDefinitionXML += "<loginproperty>Email</loginproperty>";
entityDataSourceProviderDefinitionXML += "</provider>";
entityDataSourceProviderDefinitionXML += "</dataproviders>";
entityDataSourceProvider .Items[0].DefinitionXml = entityDataSourceProviderDefinitionXML;
//Custom provider name which is added in addinprovider table
entityDataSourceProvider .Items[0].Provider = "customsqlprovider";
entityDataSourceProvider .Items[0].InstanceName = "sqlproviderCustom";
entityDataSourceProvider .Items[0].DisplayName = "Custom Provider";
entityDataSourceProvider .Items[0].Entity = entity;
// Update skelta list entry with the custom entry in SKEntityDataSourceProvider for user provider entityDataSourceProvider.Items[0].Save();
The provider name value customsqlprovider should be same as the AddInProvider Name column value.
Using Table Entry for steps 1 & 2:
The definition XML for entity should be matching the properties for entity data source provider.
Update SKEntity Set DefinitionXML = '<entity type="user"><properties><property name="UserId" type="string" purpose="identifier" /><property name="Name" type="string" purpose="name"/><property name="Email" type="string" purpose="email"/></properties></entity>%%$#@@!!!*&%%$#@@!!!*&'
Where Name = 'UserEntity'
Make sure to update the connection string information in definition XML with the appropriate value. The provider column value should be same as the name column value inserted in SKAddInProviders table.
Note: Also, ensure that the query given below updates the row for the AVEVA Work Tasks List User Entity Data Source Provider and not the Role Entity Data Source Provider.
Update SKEntityDataSourceProvider Set DefinitionXML ='<dataproviders><provider name="customsqlprovider" type="Custom Sql Provider"><properties><property name="UserId" type="guid" purpose="identifier"/><property name="Name" type="string" purpose="name"/><property name="Email" type="string" purpose="email"/><property name="Password" type="string" purpose="password"/></properties><datasource>server=localhost;
database=SkeltaUsers;uid=sa;pwd=XXX</datasource><SourceTable>SqlUsers</SourceTable>
<loginproperty>Email</loginproperty></provider></dataproviders>',
DisplayName='Custom Provider', Provider='customsqlprovider', InstanceName='sqlproviderCustom' Where DisplayName ='Skelta List' and EntityId=(Select Id from SKEntity where Name='UserEntity')
Note: Connection string should be changed.
Verification:
The above code creates an entry in SKEntity table. The entry in Repository DB can be verified in database by running the query select * from SKEntity Where Name= 'UserEntity'and Application='Sample Repository'
|
Column Name |
Value |
|---|---|
|
ID |
Auto generated |
|
MappingEntityId |
Null |
|
Application |
Sample Repository |
|
Name |
User Entity |
|
Mapping Table |
SKVirtualActor |
|
DefinitionXML |
<entity type="user"><properties><property name="UserId" type="string" purpose="identifier" /><property name="Name" type="string" purpose="name"/><property name="Email" type="string" purpose="email"/></properties></entity>%%$#@@!!!*& |
|
AddInProviderId |
Default AddInProviderId |
|
LastUpdatedDateTime |
Date time value |
The above code creates an entry in SKEntityDataSourceProvider table. The entry in Repository DB can be verified in database by running the query select * from SKEntityDataSourceProvider Where DisplayName='Custom Provider'
|
Column Name |
Value |
|---|---|
|
ID |
Auto generated |
|
Application |
Sample Repository |
|
Entity ID |
Copy the Id Column value of SKEntity of RoleEntity row here. |
|
DisplayName |
Custom Provider |
|
DefinitionXML |
<dataproviders> <provider name="customsqlprovider" type="Custom Sql Provider"><properties> <property name="UserId" type="guid" purpose="identifier"/> <property name="Name" type="string" purpose="name"/> <property name="Email" type="string" purpose="email"/> <property name="Password" type="string" purpose="password"/> </properties> <datasource>server=localhost;database=SkeltaUsers;uid=sa;pwd=XXX</datasource><SourceTable>SqlUsers</SourceTable><loginproperty>Email</loginproperty></provider></dataproviders> |
|
Provider |
customsqlprovider |
|
Instance Name |
sqlproviderCustom |
|
LastUpdatedDateTime |
Date time value |
-
Verify whether the Custom User Entity Data Source Provider is configured correctly or not
Verification:
The above code updates the entries required for configuring Custom User Entity Data Source Provider. Now, we should be able to see the provider in Repository list page. The previous entry of "List" will be updated with "Custom Provider".
If you get a message "No Provider Available" in the repository list page, cross check the Logger Console for a detailed exception for the cause.
-
Check the calls made to the custom user entity data source provider.
If there is no exception then we could also create the Actor object API to check the calls made to the custom user entity data source provider.
DLL REFERENCE
Skelta.HWS
Workflow.NET.NET2
The parameters passed to the Actor object are application object & real user id. Real user id can be formed by prefixing provider instance name and special characters "::" to the unique identifier value of user. We have used UserId column value for Kevin.

Sample code:
Skelta.HWS.Actor actor = new Actor(new ApplicationObject("Sample Repository"), "sqlproviderCustom::c6a7170a-6a35-4f79-8688-150d0ac8fe15");
object identifierValue = actor.Resource.Properties.Identifier.Value;
string Name = actor.Resource.Properties.Name.Value.ToString();
string Email = actor.Resource.Properties.Email.Value.ToString();
The above code also creates an entry to SKVirtualActor table, this can be checked using query. Select * from SKVirtualActor Where Name='Kevin'