locked
PowerShell Script to "load" a new Data Model Module? RRS feed

  • Question

  • Hi,

    I've created a new Data Model Module and exported the Assembly + EFM artifacts (.msl, .ssdl, .csdl).  The Web UI recognized my new Data Model, but throws an exception (file not found) when trying to Add a new resource when the resource-type comes from my new model.  Do I need to run one of the PowerShell scripts to place my new Assembly (.dll file) into the appropriate folders for the Web-UI to Reflect on?

    Any help appreciated.


    Devhead

    Wednesday, February 8, 2012 4:46 PM

Answers


  • Thanks for your patience.

    It is strongly recommended to use the PowerShell script to create and register a new Zentity Data Model to the Zentity. Later on you can
    use Zentity application to edit, add or delete resources.

    The steps you have covered so far only create a new Zentity Data Model, but it does not create or update the Zentity services.
    Until unless the Zentity services are updated you cannot use the Zentity applications (WebUI, Zentity Resource Manager, Zentity Visual Explorer etc.) for those particular resources. The Zentity Data Service acts as a bridge between the Zentity Client side
    applications (WebUI etc.) and Zentity Core. The PowerShell script not only adds the new Entity to the Zentity but also
    updates the “Client side proxy” to work with those entities in the Zentity Client applications.

    Now, the concrete part. When you use the following PowerShell script

    Create-ZentityDataModelClientSetup  “C:\Program
    Files (x86)\Zentity\Samples\US Presidents Sample\RDFs\PivotDemo.xml”  “C:\Program Files (x86)\Zentity\Samples\US
    Presidents Sample\RDFS\PivotDemo.xsd”  PivotDemo.Model

    You not only add the new Entity into the Zentity Data Model but also update the Client side proxy so that the newly added entity
    can be used in client applications. Using code, so far, you have successfully added your model to the ZDM now you should run the PowerShell script to update the proxy. To do this follow the steps provided below.

    1. Open the PowerShell in the admin mode.
    2. Change its location to the PowerShell script folder under the Zentity installation.
    3. Load the script . ./Zentity-ConfigureDataModel.ps1
    4. Run the command Update-ZentityDataModelClientSetup  (no parameters).

    The above command will update the client side proxies for the newly added Entities.

    NOTE:-

    When you run the command Create-ZentityDataModelClientSetup  from the script file Zentity-ConfigureDataModel.ps1,
    it calls the PowerShell function Create-ZentityDataModelFromXmlFiles which is placed in the DataModelService.ps1
    script file. This function creates the Zentity Data Model (which you have done with code) and then calls the Update-ZentityDataModels which is in the file named Common.ps1. This function then calls the Update-ZentityDataModelClientSetup command which is placed under the Zentity-ConfigureDataModel.ps1 file (this part you have not done in code).
    Please let me know if you have any further query or some part is not clear.

    -Regards


    • Proposed as answer by Kalnemi Monday, February 13, 2012 8:14 AM
    • Marked as answer by Gump Monday, February 13, 2012 9:38 PM
    Monday, February 13, 2012 8:14 AM

All replies

  • Got a little further by Brute Force and Ignorance approach of just dropping the Assembly for my custom Data Model Module into the /bin folder of the Web application.  Now, I can go through the steps to add a new resource in the Web UI, but when I try to save it, I get another exception "Mapping and metadata information could not be found for Entitytype <Entity from my custom Data Model module>.

    Do I need to copy the .csdl or other EFM files to some location?

        Exception message: Mapping and metadata information could not be found for EntityType 'Zentity.Ontology.OntologicalEntity'.

       at System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType)

       at System.Data.Objects.ObjectContext.ValidateEntitySet(EntitySet entitySet, Type entityType)

       at System.Data.Objects.ObjectContext.VerifyRootForAdd(Boolean doAttach, String entitySetName, IEntityWrapper wrappedEntity, EntityEntry existingEntry, EntitySet& entitySet, Boolean& isNoOperation)

       at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity)

       at Zentity.Core.ZentityContext.AddToResources(Resource resource)

       at Zentity.Web.UI.ToolKit.ResourceDataAccess.SaveResource(Boolean isEditMode, Resource resourceObj)

       at Zentity.Web.UI.ToolKit.ResourceProperties.SaveResourceProperties(Resource resource, ZentityContext context)

       at Zentity.Web.UI.ToolKit.ResourceProperties.SaveResourceProperties()

       at UserControls_CreateResource.SaveResource()

       at UserControls_CreateResource.Submit_Click(Object sender, EventArgs e)

       at System.Web.UI.WebControls.Button.OnClick(EventArgs e)

       at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)

       at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)

       at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)

       at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)

       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)


    Devhead

    Wednesday, February 8, 2012 6:37 PM
  • Can you please list out the steps you followed to create the data model. It is recommended to use the PowerShell script to create and
    register new data model as it takes care of all the intermediate steps and updating the dependencies.

    I am trying to repro the exception at my end and update you once done with steps to resolve this issue. Now, I suggest to check the
    presence of the generated assembly in the following folders.

    ..\Zentity\Pivot\Publishing

    ..\Zentity\PowerShell scripts\Assemblies

    ..\Zentity\ZentityWebSite\DataService\bin

    ..\Zentity\ZentityWebSite\ResourceService\bin

    ..\Zentity\ZentityWebSite\SearchService\bin

    ..\Zentity\ZentityWebSite\SecurityService\bin

    ..\Zentity\ZentityWebSite\VisualExplorer\bin

    -Regards

    Thursday, February 9, 2012 2:19 PM
  • Thanks Kalnemi,

    Here are the steps:

    1) Installed release version of Zentity client and server (2.1)  Both installed on same box: Server 2K8-R2, SQL 2K8-R2

    2) Verified Resource Manager, Visual Explorer, Pivot Viewer and Web UI are working (able to add new resources, link them, view them)

    3) Using VS2010 Ultimate, created C# console app project.  Added Zentity and Zentity.Rdf projects to same solution (for debugging).  Added references to Zentity and Zentity.Rdf projects in Console App.

    4) Compiled and executed Console App (See Below).  No exceptions thrown during execution.

    5) Copied newly created Assembly "Zentity.Extensions.Ontology" to locations:

    • ..\Zentity\Pivot\Publishing
    • ..\Zentity\PowerShell scripts\Assemblies  (** This folder does not exist on my install **)
    • ..\Zentity\ZentityWebSite\DataService\bin
    • ..\Zentity\ZentityWebSite\ResourceService\bin
    • ..\Zentity\ZentityWebSite\SearchService\bin
    • ..\Zentity\ZentityWebSite\SecurityService\bin
    • ..\Zentity\ZentityWebSite\VisualExplorer\bin

    6) Open the Zentity Resource Manager, Log in with default Admin Account.

    7) Click Add->Select Data Model=Zentity.Extensions.Ontology, ResourceType=Ontological Entity

    8) Fill in Summary and Meta-Data tabs, Click Save.  Results in:

    Contents of console app:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.Serialization;
    using System.Data.Entity;
    using Zentity.Core;
    using System.IO;
    
    
    namespace CustomDataModelModule1
    {
        class Program
        {
            const string extensionsNameSpace = "Zentity.Extensions.Ontology";
            const string extensionAssemblyName = "Zentity.Extensions.Ontology";
    
            const string connectionStringFormat = @"provider=System.Data.SqlClient;
                    metadata=res://Zentity.Core; provider connection string='Data Source=.;
                    Initial Catalog=Zentity;Integrated Security=True;MultipleActiveResultSets=True'";
    
            static void Main(string[] args)
            {
                using (ZentityContext context = new ZentityContext(connectionStringFormat))
                {
                    ResourceType resourceTypeResource = context.DataModel.Modules["Zentity.Core"].ResourceTypes["Resource"];
    
                    // Create Data Model module.
                    DataModelModule module = new DataModelModule { NameSpace = extensionsNameSpace };
                    context.DataModel.Modules.Add(module);
    
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    // Create OntologicalEntity resource type.
                    ResourceType resourceTypeOntologicalEntity = new ResourceType
                    {
                        Name = "OntologicalEntity",
                        BaseType = resourceTypeResource,
                        Description = "Ontological Entity",
                        Uri = "SomeURITest"
                    };
    
                    // Add Self NavigationProperties
                    NavigationProperty navIsAMoreSpecificFormOf = new NavigationProperty { Name = "IsAMoreSpecificFormOf" };
                    resourceTypeOntologicalEntity.NavigationProperties.Add(navIsAMoreSpecificFormOf);
                    NavigationProperty navIsAMoreGenericFormOf = new NavigationProperty { Name = "IsAMoreGenericFormOf" };
                    resourceTypeOntologicalEntity.NavigationProperties.Add(navIsAMoreGenericFormOf);
                    Association associationSpecificGeneric = new Association
                    {
                        Name = "OntologicalEntityHasMoreGenericForms",
                        SubjectNavigationProperty = navIsAMoreSpecificFormOf,
                        ObjectNavigationProperty = navIsAMoreGenericFormOf,
                        SubjectMultiplicity = AssociationEndMultiplicity.Many,
                        ObjectMultiplicity = AssociationEndMultiplicity.Many
                    };
    
    
                    NavigationProperty navSynonyms = new NavigationProperty { Name = "Synonyms" };
                    resourceTypeOntologicalEntity.NavigationProperties.Add(navSynonyms);
                    NavigationProperty navIsSynonymFor = new NavigationProperty { Name = "IsSynonymFor" };
                    resourceTypeOntologicalEntity.NavigationProperties.Add(navIsSynonymFor);
                    Association associationSynonymous = new Association
                    {
                        Name = "OntologicalEntityHasSynonyms",
                        SubjectNavigationProperty = navSynonyms,
                        ObjectNavigationProperty = navIsSynonymFor,
                        SubjectMultiplicity = AssociationEndMultiplicity.Many,
                        ObjectMultiplicity = AssociationEndMultiplicity.Many
                    };
    
                    // Add Scalar Properties
    
                    // For now, the "Title" in the base "Resource" will hold the "Value" (word or phrase)
                    // Neighborhood might need to be a first-class entity in the model with a NavigationProperty for OntologicalEntity.
                    ScalarProperty Neighborhood = new ScalarProperty { Name = "Neighborhood", DataType = DataTypes.String, MaxLength = 4000 };
                    resourceTypeOntologicalEntity.ScalarProperties.Add(Neighborhood);
    
    
                    //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    
                    module.ResourceTypes.Add(resourceTypeOntologicalEntity);
    
                    // Synchronize the in-memory models with the backend.
                    context.DataModel.Synchronize();
    
                    // Generate Extensions Assembly.
                    using (FileStream fout = new FileStream(@"D:\Zentity\Zentity.Extensions.Ontology.dll", FileMode.Create, FileAccess.Write))
                    {
                        byte[] rawAssembly = context.DataModel.GenerateExtensionsAssembly(
                            extensionAssemblyName, true, null, new string[] { extensionsNameSpace }, null);
                        fout.Write(rawAssembly, 0, rawAssembly.Length);
                    }
    
                    // Generate Entity Framework artifacts.
                    EFArtifactGenerationResults results = context.DataModel.GenerateEFArtifacts(extensionsNameSpace);
                    results.Csdls.Where(tuple => tuple.Key == "Zentity.Core").First().Value.Save(@"D:\Zentity\ExtendedCore.csdl");
                    results.Csdls.Where(tuple => tuple.Key == extensionsNameSpace).First().Value.Save(@"D:\Zentity\Zentity.Extensions.Ontology.csdl");
                    results.Msl.Save(@"D:\Zentity\Consolidated.msl");
                    results.Ssdl.Save(@"D:\Zentity\Consolidated.ssdl");
                }
            }
        }
    
    }
    

    Devhead

    Thursday, February 9, 2012 2:57 PM
  • Looks like the ZentityResourceService is the culprit here.  The ZentityResourceService.log file has entries like: 

    The custom Data Model Module Assembly is definitely present in the ..\Zentity\ZentityWebSite\ResourceService\bin folder and when executing the GenerateExtensionsAssembly method, I am passing "true" for embedMetadataFilesAsResources argument.  What do I need to do for the ResourceService to be able to "find" my Mapping and metadata for the custom Assembly?

    ----------------------------------------
    General Error: 100 : Timestamp: 2/9/2012 4:44:28 PM
    Message: HandlingInstanceID: 43c23af7-c874-409b-a42f-11a1e45567fc
    An exception of type 'System.InvalidOperationException' occurred and was caught.
    --------------------------------------------------------------------------------
    02/09/2012 10:44:28
    Type : System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    Message : Mapping and metadata information could not be found for EntityType 'Zentity.Extensions.Ontology.OntologicalEntity'.
    Source : System.Data.Entity
    Help link : 
    Data : System.Collections.ListDictionaryInternal
    TargetSite : System.Data.Metadata.Edm.TypeUsage GetTypeUsage(System.Type)
    Stack Trace :    at System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType)
       at System.Data.Objects.ObjectContext.ValidateEntitySet(EntitySet entitySet, Type entityType)
       at System.Data.Objects.ObjectContext.VerifyRootForAdd(Boolean doAttach, String entitySetName, IEntityWrapper wrappedEntity, EntityEntry existingEntry, EntitySet& entitySet, Boolean& isNoOperation)
       at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity)
       at Zentity.Core.ZentityContext.AddToResources(Resource resource)
       at Zentity.Services.Web.Resources.Business.Components.ResourcesHandler.AddResources(ResourceEntity resource)
       at Zentity.Services.Web.Resources.ResourceService.AddResource(ResourceEntity resource, List`1 permissions)
    
    Additional Info:
    
    MachineName : DEV-WS-RON
    TimeStamp : 2/9/2012 4:44:28 PM
    FullName : Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
    AppDomainName : /LM/W3SVC/2/ROOT/ResourceService-4-129732779209712160
    ThreadIdentity : 
    WindowsIdentity : DEV-WS-RON\rkegge
    
    Category: General
    Priority: 5
    EventId: 100
    Severity: Error
    Title:Enterprise Library Exception Handling
    Machine: DEV-WS-RON
    App Domain: /LM/W3SVC/2/ROOT/ResourceService-4-129732779209712160
    ProcessId: 2968
    Process Name: C:\Windows\SysWOW64\inetsrv\w3wp.exe
    Thread Name: 
    Win32 ThreadId:7968
    Extended Properties: 
    ----------------------------------------


    Devhead

    Thursday, February 9, 2012 4:59 PM

  • Thanks for your patience.

    It is strongly recommended to use the PowerShell script to create and register a new Zentity Data Model to the Zentity. Later on you can
    use Zentity application to edit, add or delete resources.

    The steps you have covered so far only create a new Zentity Data Model, but it does not create or update the Zentity services.
    Until unless the Zentity services are updated you cannot use the Zentity applications (WebUI, Zentity Resource Manager, Zentity Visual Explorer etc.) for those particular resources. The Zentity Data Service acts as a bridge between the Zentity Client side
    applications (WebUI etc.) and Zentity Core. The PowerShell script not only adds the new Entity to the Zentity but also
    updates the “Client side proxy” to work with those entities in the Zentity Client applications.

    Now, the concrete part. When you use the following PowerShell script

    Create-ZentityDataModelClientSetup  “C:\Program
    Files (x86)\Zentity\Samples\US Presidents Sample\RDFs\PivotDemo.xml”  “C:\Program Files (x86)\Zentity\Samples\US
    Presidents Sample\RDFS\PivotDemo.xsd”  PivotDemo.Model

    You not only add the new Entity into the Zentity Data Model but also update the Client side proxy so that the newly added entity
    can be used in client applications. Using code, so far, you have successfully added your model to the ZDM now you should run the PowerShell script to update the proxy. To do this follow the steps provided below.

    1. Open the PowerShell in the admin mode.
    2. Change its location to the PowerShell script folder under the Zentity installation.
    3. Load the script . ./Zentity-ConfigureDataModel.ps1
    4. Run the command Update-ZentityDataModelClientSetup  (no parameters).

    The above command will update the client side proxies for the newly added Entities.

    NOTE:-

    When you run the command Create-ZentityDataModelClientSetup  from the script file Zentity-ConfigureDataModel.ps1,
    it calls the PowerShell function Create-ZentityDataModelFromXmlFiles which is placed in the DataModelService.ps1
    script file. This function creates the Zentity Data Model (which you have done with code) and then calls the Update-ZentityDataModels which is in the file named Common.ps1. This function then calls the Update-ZentityDataModelClientSetup command which is placed under the Zentity-ConfigureDataModel.ps1 file (this part you have not done in code).
    Please let me know if you have any further query or some part is not clear.

    -Regards


    • Proposed as answer by Kalnemi Monday, February 13, 2012 8:14 AM
    • Marked as answer by Gump Monday, February 13, 2012 9:38 PM
    Monday, February 13, 2012 8:14 AM
  • Kalnemi,

    Thanks!  That did the trick. 

    Just a couple of follow-up questions:

    1) I can delete a custom data model that was added using the powershell scripts, but would like to do the same with the ScholarlyWorks data model.  This seems to be a bit trickier.  Do you have the steps to do this?

    2) Using the RDF schema approach to define the model seems easier, but it seems like there is less control over defining the navigation properties.  E.g.  How would I define the navigation property in my model (above) for "OntologicalEntityHasMoreGenericForms".  I don't see a way to specify multiplicity or inherit from the Base Zentity.Core.Resource.  Can you point me to some guidance on specifying navigation properties using RDF?  In other words, how do I do the equivalent of (below) using RDF?

                    Association associationSpecificGeneric = new Association
                   
    {
                       
    Name = "OntologicalEntityHasMoreGenericForms",
                       
    SubjectNavigationProperty = navIsAMoreSpecificFormOf,
                       
    ObjectNavigationProperty = navIsAMoreGenericFormOf,
                       
    SubjectMultiplicity = AssociationEndMultiplicity.Many,
                       
    ObjectMultiplicity = AssociationEndMultiplicity.Many
                   
    };


    Devhead

    Monday, February 13, 2012 9:45 PM
    1. You cannot delete/update the model that is shipped from Microsoft. There is no way to delete the model, until you do some
      code customization. The trick will work but you need to check the dependencies at your end, if any.
      When you will try to delete the ScholarlyWork Model using PowerShell function , Delete-ZentityDataModel Zentity.ScholarlyWorks it will generate an exception as shown in the below screen shot.

    Now the trick is, open the Zentity source code in Visual Studio --> Go to the uppermost function in the stack in the screen shot, which is Zentity.Core.DataModel.ValidateMsShippedModuleChanges (DataModel originalModel, DataModel newModel). Comment all the inside code, build the project and replace all Zentity.Core.DataModel.dll under Zentity installation with this one. Now you can run the powershell script as usual to delete the ScholarlyWorks.


    2) The Zentity RDF interpreter does not provide that much flexibility. The only way to achieve the same is to modify it
    manually in schema files, csdl, msl, and ssdl and then calling DataModel.Synchronize() method.

    I am trying below to summarize how Zentity process the NavigationProperty from the RDF file using one example from USPresident
    sample. USPresident sample has one below property

    <rdf:Property rdf:about="PrecededBy" >
        <
    rdfs:domain rdf:resource="USPresident"/>
        <
    rdfs:range rdf:resource="USPresident"/>
    </
    rdf:Property>

     In English it says that “An instance of USPresident is PrecedeBy (aka relationship, predicate, association) by an another instances (aka multiplicity, zero or one, Many) of USPresident. In reverse, suppose I need to represent the fact “The Employee has an account in Bank”. This can be represented in RDF as
    <rdf:Property rdf:about="hasAnAccount" >
        <
    rdfs:domain rdf:resource="Employee"/>
        <
    rdfs:range rdf:resource="Bank"/>
    </
    rdf:Property>

    The domain and range words are imported from the set-theoretic mathematics. The domain is the subject and range is the object. Now for multiplicity. RDF does not have any concept of cardinality. Associations are always Many-to-Many. You cannot define one-to-one association.
    You can define ZeroOrOne if you need using the schema files.

    Again, with USPresident example.

    <rdf:Property rdf:about="PrecededBy" >
        <
    rdfs:domain rdf:resource="USPresident"/>
        <
    rdfs:range rdf:resource="USPresident"/>
    </
    rdf:Property>

    On seeing the above, Zentity creates an association named USPresident_PrecededBy_USPresident. In the domain it creates a
    navigation property called PrecededBy in the range it creates a navigation property called PrecededBy_Inverse. Since, here both subject and object classes are the same so both will be created under the USPresident entity. Here, the user has the limitation of not able to provide custom names to the association or navigation property but can achieve the same using schema files. I am also looking into other ways for doing this and going through some resource on RDF on net. I will update in this thread if I find some other way to do this.

    Please let me know of any further query.

    -Regards  

    • Proposed as answer by Kalnemi Wednesday, February 15, 2012 2:05 PM
    Wednesday, February 15, 2012 2:05 PM