locked
SPD New External Content Type from existing .NET assembly error RRS feed

  • Question

  • I have been working with Sharepoint BCS for the past few weeks and have been mostly successful in overcoming issues that have cropped up. I have finally come across one that I can't seem to correct.

    The scenario:

    • I have created a .NET assembly(BCS model) that allows me to connect to a MySQL database to return lists/items and update items.
    • The automated deployment process through visual studio(Build => Deploy) have been successful in creating an external content type to the target SharePoint site.
    • The created external content type is bound to the existing read list method/read item method/update method and operates as intended(read/write functions).
    • I now would like to add a secondary External Content Type and leverage the existing read list with a new read item(already created in the BCS).

    The problem:

    • After deployment of the BCS, SharePoint sees the updated .NET assembly information(the new readItem method), but when I go to create a new external content type and target the existing readList method as the new content type's Read List operation, I am presented with the following error:

      "This operation is based on a method with complex data types in its signature. To be supported, each complex type referenced in the method signature must have a default constructor that does not require any parameters. Update the .NET connectivity assembly code and redeploy it to the Business Connectivity Services before retrying."

    Attempted resolutions:

    • I have refreshed the .NET assembly references on the target SharePoint site.
    • I have added a default constructor to the object that is being returned to the site.

    Information on the return object:

    • The return object contains data from three tables, so I created a class that contained the proper fields and then populate those fields via query. The populated object is returned to the SharePoint site.

    To summarize/reiterate, the default deployment process creates the proper content type, but I am unable to use the existing functioning Read List method again when I go to manually create a second content type.

    Thanks in Advance,

    TB


    EDIT: I just realized that this may not be the most appropriate forum for this. Can someone move this to the proper forum? Sorry!
    • Edited by Tb- Tuesday, March 13, 2012 5:37 PM
    Tuesday, March 13, 2012 5:26 PM

Answers

  • Thanks, now I understand the problem. In order to avoid it you may use List<T> class instead of IEnumerable<T>. List<T> class has default constructor. So please modify ReadList operation in your first ECT as follows and you will be able to use utilize this method in SharePoint designer as you wish.

    public static List<Entity1> ReadList()
    {
        classicmodelsEntities db = new classicmodelsEntities(connectionString);
        return db.offices.Select(item => new Entity1()
        {
            officeCode = item.officeCode,
            city = item.city,
            phone = item.phone,
            addressLine = item.addressLine1,
            country = item.country
        }).ToList();
    }


    Dmitry

    Lightning Tools LogoLightning Tools Check out our SharePoint tools and web parts

    • Marked as answer by Pengyu Zhao Monday, March 26, 2012 2:18 AM
    Thursday, March 15, 2012 4:43 PM

All replies

  • Hi,

    Please clarify how the second external content type looks like. Does it read the data from the created External List rather than MySQL database? Post please here snippet code.


    Dmitry

    Lightning Tools LogoLightning Tools Check out our SharePoint tools and web parts

    Wednesday, March 14, 2012 9:33 AM
  • The external content type is a mirror of the original; it reads information from the MySQL database through the same .NET assembly that the first content type is using.

    What code are you looking for exactly? The methods all function as expected; the read list method returns all data, the original read item returns the expected item, and the second read item returns the expected item. Are you looking for something in particular from the BCS model xml?

    I'm starting to think that the issue is in fact that the read list operation inside sharepoint designer does not like the fact that it is seeing a return type of an Ienumerable(when you specify a return collection in a BCS model, it defaults to IEnumerable). IEnumerable being an interface that has no constructor...


    • Edited by Tb- Wednesday, March 14, 2012 2:07 PM
    Wednesday, March 14, 2012 2:07 PM
  • Are you using ODBC in order to work with MySQL?

    Dmitry

    Lightning Tools LogoLightning Tools Check out our SharePoint tools and web parts

    Wednesday, March 14, 2012 8:08 PM
  • No, the .NET assembly is using the MySQL/.NET connector and I'm pulling the information via linq to entities.
    Wednesday, March 14, 2012 8:17 PM
  • To be honest the problem is still unclear for me. For example I can create External content type in Visual Studio using MySQL .net connector. This external content type works fine in SharePoint. You may create your ECTs the same way. Here is the code and BDC Model:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace BdcModelProject1.BdcModel1
    {    
        public class Entity1
        {
            public int officeCode { get; set; }
            public string city { get; set; }
            public string phone { get; set; }
            public string addressLine { get; set; }
            public string country { get; set; }
        }
    
        public class Entity1Service
        {
            private static string connectionString = "metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=MySql.Data.MySqlClient;provider connection string='server=taurus;User Id=testuser;password=12345;Persist Security Info=True;database=classicmodels'";
    
            public static Entity1 ReadItem(int id)
            {
                classicmodelsEntities db = new classicmodelsEntities(connectionString);
                return db.offices.Select(item => new Entity1()
                {
                    officeCode = item.officeCode,
                    city = item.city,
                    phone = item.phone,
                    addressLine = item.addressLine1,
                    country = item.country
                }).FirstOrDefault(item => item.officeCode == id);
            }
            public static IEnumerable<Entity1> ReadList()
            {
                classicmodelsEntities db = new classicmodelsEntities(connectionString);
                return db.offices.Select(item => new Entity1()
                {
                    officeCode = item.officeCode,
                    city = item.city,
                    phone = item.phone,
                    addressLine = item.addressLine1,
                    country = item.country
                });
            }
        }
    }

    <?xml version="1.0" encoding="utf-8"?>
    <Model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/windows/2007/BusinessDataCatalog" Name="BdcModel1">
      <LobSystems>
        <LobSystem Name="BdcModel1" Type="DotNetAssembly">
          <LobSystemInstances>
            <LobSystemInstance Name="BdcModel1" />
          </LobSystemInstances>
          <Entities>
            <Entity Name="Entity1" Namespace="BdcModelProject1.BdcModel1" EstimatedInstanceCount="1000" Version="1.0.0.47">
              <Properties>
                <Property Name="Class" Type="System.String">BdcModelProject1.BdcModel1.Entity1Service, BdcModel1</Property>
              </Properties>
              <Identifiers>
                <Identifier Name="officeCode" TypeName="System.Int32" />
                <!-- TODO: Change the name of the ID and if needed the TypeName of your identifier. -->
              </Identifiers>
              <Methods>
                <!-- start finder method -->
                <Method Name="ReadList">
                  <!-- TODO: Change the name of the method if needed. -->
                  <Parameters>
                    <Parameter Direction="Return" Name="returnParameter">
                      <TypeDescriptor TypeName="System.Collections.Generic.IEnumerable`1[[BdcModelProject1.BdcModel1.Entity1, BdcModel1]]" IsCollection="true" Name="Entity1List">
                        <TypeDescriptors>
                          <TypeDescriptor TypeName="BdcModelProject1.BdcModel1.Entity1, BdcModel1" Name="Entity1">
                            <TypeDescriptors>
                              <TypeDescriptor TypeName="System.Int32" Name="officeCode" IdentifierName="officeCode" IsCollection="false" />
                              <!-- TODO: Add TypeDescriptors when you add properties to Entity1. -->
                              <TypeDescriptor Name="city" TypeName="System.String" IsCollection="false" />
                              <TypeDescriptor Name="phone" TypeName="System.String" IsCollection="false" />
                              <TypeDescriptor Name="addressLine" TypeName="System.String" IsCollection="false" />
                              <TypeDescriptor Name="country" TypeName="System.String" IsCollection="false" /></TypeDescriptors>
                          </TypeDescriptor>
                        </TypeDescriptors>
                      </TypeDescriptor>
                    </Parameter>
                  </Parameters>
                  <MethodInstances>
                    <MethodInstance Type="Finder" ReturnParameterName="returnParameter" Default="true" Name="ReadList" DefaultDisplayName="Entity1 List" />
                  </MethodInstances>
                </Method>
                <!-- end finder method -->
                <!-- start specific finder method -->
                <Method Name="ReadItem">
                  <Parameters>
                    <Parameter Direction="In" Name="id">
                      <TypeDescriptor TypeName="System.Int32" IdentifierName="officeCode" Name="id" IsCollection="false" />
                    </Parameter>
                    <Parameter Direction="Return" Name="returnParameter">
                      <TypeDescriptor TypeName="BdcModelProject1.BdcModel1.Entity1, BdcModel1" Name="Entity1">
                        <TypeDescriptors>
                          <TypeDescriptor TypeName="System.Int32" IdentifierName="officeCode" Name="officeCode" IsCollection="false" />
                          <!-- TODO: Add TypeDescriptors when you add properties to Entity1. -->
                          <TypeDescriptor Name="addressLine" TypeName="System.String" IsCollection="false" />
                          <TypeDescriptor Name="city" TypeName="System.String" IsCollection="false" />
                          <TypeDescriptor Name="country" TypeName="System.String" IsCollection="false" />
                          <TypeDescriptor Name="phone" TypeName="System.String" IsCollection="false" /></TypeDescriptors>
                      </TypeDescriptor>
                    </Parameter>
                  </Parameters>
                  <MethodInstances>
                    <MethodInstance Type="SpecificFinder" ReturnParameterName="returnParameter" Default="true" Name="ReadItem" DefaultDisplayName="Read Entity1" />
                  </MethodInstances>
                </Method>
                <!-- end specific finder method -->
              </Methods>
            </Entity>
          </Entities>
        </LobSystem>
      </LobSystems>
    </Model>


    Dmitry

    Lightning Tools LogoLightning Tools Check out our SharePoint tools and web parts


    Thursday, March 15, 2012 1:36 PM
  • Hi Dmitry,

    Thank you for your response. I'm not sure you are understanding what is and is not functioning.

    What currently exists and functions:

    • I created the BCS model in the same way that you have shown above.
      This model consists of 1 entity that contains 1 read list operation, 1 update operation, and 2 read item operations.
    • When deployed through the Visual Studio deployment methodology, SharePoint gets 1 external content type with the aforementioned operations(1 read item becomes the default).
    • The created external content type works as expected; creation of lists, viewing, editing etc, all normal.
    • The .NET assembly is registered with SharePoint and is visable from a SharePoint Designer perspective; I can see the .NET assembly connection and all 4 methods from SharePoint Designer.

    What does not work and I would like to do:

    • Within SharePoint Designer, if I were to manually create a second external content type(in addition to the one that gets deployed), I am unable to bind the existing .NET assembly read list method to the read list operation of this new content type(see the first post's error that came from SPD). This prevents the content type from being useful as I can't create a list from it.
    • When I attempt to use the existing read list method as the new content type's read list operation, the error that was in the original post is generated.

    I'm not sure I can explain it any clearer than that.



    • Edited by Tb- Thursday, March 15, 2012 2:21 PM
    Thursday, March 15, 2012 2:20 PM
  • Thanks, now I understand the problem. In order to avoid it you may use List<T> class instead of IEnumerable<T>. List<T> class has default constructor. So please modify ReadList operation in your first ECT as follows and you will be able to use utilize this method in SharePoint designer as you wish.

    public static List<Entity1> ReadList()
    {
        classicmodelsEntities db = new classicmodelsEntities(connectionString);
        return db.offices.Select(item => new Entity1()
        {
            officeCode = item.officeCode,
            city = item.city,
            phone = item.phone,
            addressLine = item.addressLine1,
            country = item.country
        }).ToList();
    }


    Dmitry

    Lightning Tools LogoLightning Tools Check out our SharePoint tools and web parts

    • Marked as answer by Pengyu Zhao Monday, March 26, 2012 2:18 AM
    Thursday, March 15, 2012 4:43 PM