1
votes

Implementing a custom readwrite provider by following the Northwind DataProvider. Problem is when inserting a new item to the content tree, it shows two copies of the item, the other one is basically "image" i.e, same ID and cannot be edited, cannot even click on that "image" item. But any changes to the real item will show on the "image" item (editing, deleting). I also checked the external data base (SQL Server) table, only one record gets created. So the mystery is that how Sitecore displays the item twice under the content tree.

Sorry i dont have enough reputation to post a screeshot.

Methods codes:

  public override ItemDefinition GetItemDefinition(ID id, CallContext context)
  {
     ItemDefinition newItem = null;
     if (CanProcessChild(id, context))
     {
        object orifinalID = GetOriginalRecordID(id);

        StringBuilder sqlSelect = new StringBuilder();
        sqlSelect.AppendFormat("SELECT {0} FROM {1}", nameField, table);
        sqlSelect.Append(GetConditions(orifinalID));

        string[] result = SqlUtil.GetStringArray(sqlSelect.ToString(), connectionString);
        if (result.Length > 0)
        {
           string itemName = result[0];
           if (string.IsNullOrEmpty(itemName))
           {
              itemName = "unnamed item";
           }

           newItem = new ItemDefinition(id, itemName, MainDB.Templates[new ID(templateID)].ID, ID.Null);
           ((ICacheable)newItem).Cacheable = false;
        }
     }
     return newItem;
  }


  public override FieldList GetItemFields(ItemDefinition item, VersionUri version, CallContext context)
  {
     if (CanProcessChild(item.ID, context))
     {
        if (context.DataManager.DataSource.ItemExists(item.ID))
        {
           ReflectionUtil.CallMethod(
              typeof(ItemCache), CacheManager.GetItemCache(context.DataManager.Database),
              "RemoveItem", true, true, new object[] { item.ID });
        }

        CoreItem.Builder builder = CreateItemBuilder(item, context.DataManager);
        return builder.ItemData.Fields;
     }
     return null;

  public override bool CreateItem(ID itemID, string itemName, ID tempID, ItemDefinition parent, CallContext context)
  {
      if (new ID(templateID) == tempID && new ID(parentItemID) == parent.ID)
      {
          string fields = GetFieldsName();
          StringCollection valuesBuilder = new StringCollection();
          foreach (string field in fieldNames)
          {
              if (field == nameField)
              {
                  valuesBuilder.Add(String.Format("'{0}'", itemName));
                  continue;
              };
              if (field == idField)
              {
                  valuesBuilder.Add(String.Format("'{0}'", ID.Encode(itemID).Substring(0, 4)));
                  continue;
              };
              valuesBuilder.Add("''");
          }
          string values = StringUtil.StringCollectionToString(valuesBuilder, " ,");
          Insert(fields, values);
          IDTable.Add(ToString(), ID.Encode(itemID).Substring(0, 4), itemID, parent.ID);              
          context.Abort();
          return true;
      }
      return false;
  }

  CoreItem.Builder CreateItemBuilder(ItemDefinition item, DataManager dataManager)
  {
     CoreItem.Builder result = new CoreItem.Builder(item.ID, item.Name, item.TemplateID, dataManager);
     StringBuilder sqlSelect = new StringBuilder();
     sqlSelect.AppendFormat("SELECT {0} FROM {1}", fieldsNames, table);
     sqlSelect.Append(GetConditions(GetOriginalRecordID(item.ID)));
     using (SqlDataReader sqlResult = ExecuteReader(sqlSelect.ToString(), connectionString))
     {
        if (sqlResult.Read())
        {
           for (int i = 0; i < sqlResult.FieldCount; i++)
           {
              result.AddField(sqlResult.GetName(i), ToSitecoreValue(sqlResult.GetValue(i)));
           }
        }
     }
     return result;
  }

Basically the CreateItem method is inserting to SQL table directly and Sitecore will pick up the newly inserted item. I found that if inserting through sitecore, there is a row created in the Descendants table; but if creating from the external database table, it will not create such row and the data will be displayed properly without an "image".

I am new to sitecore and couldn't figure out what reason to this problem was.

Really appreciate your help!

1

1 Answers

1
votes

It looks like multiple providers are being used for your content tree at the same time.

If you want to ensure that no subsequent data providers are run after your data provider runs call the Abort() method on the CallContext object that is passed to your data provider.

Some more information on Data Providers on the Sitecore Community Docs.

http://sitecore-community.github.io/docs/documentation/Sitecore%20Fundamentals/Data%20Providers/Implementing%20a%20Data%20Provider/API/