diff --git a/Control/StoreGate/StoreGate/ReadHandleKeyArray.h b/Control/StoreGate/StoreGate/ReadHandleKeyArray.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9464c503a9454c3fbdecaa81f04974a2b8628e9
--- /dev/null
+++ b/Control/StoreGate/StoreGate/ReadHandleKeyArray.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef STOREGATE_READHANDLEKEYARRAY_H
+#define STOREGATE_READHANDLEKEYARRAY_H 1
+
+#include "StoreGate/VarHandleKeyArray.h"
+
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/ReadHandle.h"
+
+#include <vector>
+#include <string>
+
+namespace SG {
+
+  /**
+   * @class SG::ReadHandleKeyArray<T>
+   * @brief class to hold an array of ReadHandleKeys
+   *
+   * since it inherits from std::vector, all vector operations are 
+   * permitted.
+   *
+   * initialization can be done in three ways.
+   * 1: with an std::vector<ReadHandleKey> as a parameter
+   *    SG::ReadHandleKeyArray<foo> m_foo ( std::vector<ReadHandleKey> );
+   * 2: with an initializer list of ReadHandleKeys
+   *    SG::ReadHandleKeyArray<foo> m_foo { ReadHandleKey<foo> k1, ReadHandleKey<foo> k2 };
+   * 3: with an initializer list of std::strings, that will be used to
+   *    internally create ReadHandleKeys with those initializers
+   *    SG::ReadHandleKeyArray<foo> m_foo { "key1", "key2", "key3" };
+   */
+
+  template <class T>
+  class ReadHandleKeyArray : public VarHandleKeyArrayCommon< ReadHandleKey<T> > {
+  public:
+    /**
+     * @brief default Constructor from a ReadHandleKeyArray
+     */
+    ReadHandleKeyArray(){};
+
+    /**
+     * @brief Constructor from a ReadHandleKeyArray that takes a vector
+     * of ReaDHandleKeys
+     * @param v vector of ReadHandleKey
+     */
+    ReadHandleKeyArray( const std::vector<ReadHandleKey<T>>& v ):
+      VarHandleKeyArrayCommon<ReadHandleKey<T>> ( v ) {};
+
+    /**
+     * @brief Constructor from a ReadHandleKeyArray that takes an 
+     * initializer list of ReadHandleKeys
+     * @param l initializer list of ReadHandleKey
+     */
+    ReadHandleKeyArray( std::initializer_list<ReadHandleKey<T>> l ):
+      VarHandleKeyArrayCommon<ReadHandleKey<T>> {l} {};
+
+    /**
+     * @brief Constructor from a ReadHandleKeyArray that takes an 
+     * initializer list of std::strings.
+     * @param l initializer list of std::strings used to create the
+     *          ReadHandleKeys
+     */
+    ReadHandleKeyArray( std::initializer_list<std::string> l ):
+      VarHandleKeyArrayCommon<ReadHandleKey<T>> {l} {};
+
+    /**
+     * @brief return the type (Read/Write/Update) of handle
+     */
+    Gaudi::DataHandle::Mode mode() const { return Gaudi::DataHandle::Reader; }
+
+    /**
+     * @brief create a vector of ReadHandles from the ReadHandleKeys
+     * in the array
+     */
+    std::vector< ReadHandle<T> > makeHandles() const {
+      std::vector< ReadHandle<T> > hndl;
+      typename std::vector<ReadHandleKey<T>>::const_iterator itr;
+      for (itr = this->begin(); itr != this->end(); ++itr) {
+        hndl.push_back ( ReadHandle<T>( *itr) );
+      }
+      return ( std::move( hndl ) );
+    }
+
+  };
+
+
+} // namespace SG
+
+#endif
diff --git a/Control/StoreGate/StoreGate/SGtests.h b/Control/StoreGate/StoreGate/SGtests.h
index df7c9855e94b8e821a84d9a3b630e1220c03c9b6..d2098117579392ced5e23c93f4a50dffe0ca313f 100644
--- a/Control/StoreGate/StoreGate/SGtests.h
+++ b/Control/StoreGate/StoreGate/SGtests.h
@@ -53,5 +53,9 @@ namespace Athena_test
 
   void testBoundReset(StoreGateSvc& rSG);
 
+  void testRecordObject(StoreGateSvc& rSG);
+
+  void testWriteAux(StoreGateSvc& rSG);
+
 } //end namespace
 #endif // TEST_SGTESTS_H
diff --git a/Control/StoreGate/StoreGate/StoreGateSvc.h b/Control/StoreGate/StoreGate/StoreGateSvc.h
index 3dce2ddff9cd8e44aceca2908ffbfe10c732b6b4..64dbb169ac0825fcba0e725b0cfcbb1da1cc0ccc 100644
--- a/Control/StoreGate/StoreGate/StoreGateSvc.h
+++ b/Control/StoreGate/StoreGate/StoreGateSvc.h
@@ -511,6 +511,8 @@ public:
 
   /// set store ID. request forwarded to DataStore:
   void setStoreID(StoreID::type id);
+  /// get store ID. request forwarded to DataStore:
+  StoreID::type storeID() const;
 
 
   /** provide list of all storegate keys associated with an object.
@@ -645,6 +647,8 @@ public:
    * @param key The key as which it should be stored.
    * @param allowMods If false, the object will be recorded as const.
    * @param returnExisting If true, return proxy if this key already exists.
+   *                       If the object has been recorded under a different
+   *                       key, then make an alias.
    *
    * Full-blown record.  @c obj should usually be something
    * deriving from @c SG::DataBucket.
@@ -954,7 +958,9 @@ private:
 
   /// remove proxy from store, unless it is reset only.         
   /// provide pTrans!=0 (must match proxy...) to save time
-  /// @param forceRemove remove the proxy no matter what        
+  /// @param forceRemove remove the proxy no matter what
+  /// DO NOT USE THIS FUNCTION!
+  /// IT IS UNSAFE AND IS LIKELY TO BE REMOVED!
   StatusCode removeProxy(SG::DataProxy* proxy, const void* pTrans, 
                          bool forceRemove=false);
   ///forwarded to DataStore
diff --git a/Control/StoreGate/StoreGate/VarHandleKeyArray.h b/Control/StoreGate/StoreGate/VarHandleKeyArray.h
new file mode 100644
index 0000000000000000000000000000000000000000..3616da01c05da37858d315877283d3872e727ba7
--- /dev/null
+++ b/Control/StoreGate/StoreGate/VarHandleKeyArray.h
@@ -0,0 +1,116 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef STOREGATE_VARHANDLEKEYARRAY_H
+#define STOREGATE_VARHANDLEKEYARRAY_H 1
+
+/**
+ * @file StoreGate/VarHandleKeyArray.h
+ * @author C. Leggett
+ * @date Updated: Jun 17, 2016
+ * @brief Base class for VarHandleKeyArray for reading from StoreGate.
+ */
+
+#include "GaudiKernel/DataHandle.h"
+#include "StoreGate/VarHandleKey.h"
+
+#include <vector>
+#include <string>
+
+namespace SG {
+
+  /**
+   * @class SG::VarHandleKeyArray<T>
+   * @brief untemplated base class for VarHandleKeyArrays
+   */
+  class VarHandleKeyArray {
+  public:
+    VarHandleKeyArray(){};
+    virtual ~VarHandleKeyArray(){};
+    virtual StatusCode assign(const std::vector<std::string>& vs)=0;
+    virtual std::string toString() const = 0;
+    virtual Gaudi::DataHandle::Mode mode() const = 0;
+
+    virtual std::vector<SG::VarHandleKey*> keys() const = 0;
+
+  };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+// mixin class for common functionality
+//
+
+  /**
+   * @class SG::VarHandleKeyArrayCommon<T>
+   * @brief mixin base class for VarHandleKeyArrays, inheriting from
+   * std::vector as well as VarHandleKeyArray to provide vector-like
+   * access
+   *
+   */
+
+  template <class Base>
+  class VarHandleKeyArrayCommon : public VarHandleKeyArray, 
+                                  public std::vector<Base> {
+  public:
+    /**
+     * @brief default base Constructor of mixin
+     *
+     */
+    VarHandleKeyArrayCommon() : std::vector<Base>() {};
+    
+    /**
+     * @brief base Constructor from a VarHandleKeyArray that takes a vector
+     * @param v vector of Read/Write/UpdateHandleKey
+     */
+    VarHandleKeyArrayCommon( const std::vector<Base>& v ):
+      std::vector<Base>(v) {};
+    
+    /**
+     * @brief base Constructor from a VarHandleKeyArray that takes an 
+     * initializer list of VarHandleKeys
+     * @param l initializer list of Read/Write/UpdateHandleKey
+     */
+    VarHandleKeyArrayCommon( std::initializer_list<Base> l ):
+      std::vector<Base>{l} {};
+    
+    /**
+     * @brief base Constructor from a VarHandleKeyArray that takes an 
+     * initializer list of std::strings.
+     * @param l initializer list of std::strings used to create the
+     *          VarHandleKeys
+     */
+    VarHandleKeyArrayCommon( std::initializer_list<std::string> l ) {
+      for (auto &e : l) {
+        this->push_back( Base{e} );
+      }
+    }    
+    
+    /**
+     * @brief forward the initialization to the member VarHandleKeys
+     */
+    StatusCode initialize();
+
+    /**
+     * @brief Set the contents of the VarHandleKeyArray from a 
+     * vector of std::strings
+     * @param vs vector of initializer strings
+     */
+    StatusCode assign(const std::vector<std::string>& vs);
+
+    /**
+     * @brief string representation of the VarHandleKeyArray
+     */
+    std::string toString() const;
+
+    /**
+     * @brief create array of all base VarHandleKeys in the Array
+     */
+    std::vector<SG::VarHandleKey*> keys() const;
+    
+  };
+  
+} // namespace SG
+
+#include "StoreGate/VarHandleKeyArray.icc"
+
+#endif
diff --git a/Control/StoreGate/StoreGate/VarHandleKeyArray.icc b/Control/StoreGate/StoreGate/VarHandleKeyArray.icc
new file mode 100644
index 0000000000000000000000000000000000000000..9dd049ce85789d2bb973f8836e4f83f3716632c4
--- /dev/null
+++ b/Control/StoreGate/StoreGate/VarHandleKeyArray.icc
@@ -0,0 +1,80 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace SG {
+  //
+  // Forward the initialization to the member VarHandleKeys
+  //
+  template <class Base>
+  inline
+  StatusCode VarHandleKeyArrayCommon<Base>::initialize() {
+    StatusCode sc(StatusCode::SUCCESS);
+    typename std::vector<Base>::iterator itr;
+    for (itr = this->begin(); itr != this->end(); ++itr) {
+      if (! itr->initialize() ) {
+        sc = StatusCode::FAILURE;
+      }
+    }
+    return sc;
+  }
+
+  //
+  // Set the VarHandleKey from a string
+  //
+  template <class Base>
+  inline
+  StatusCode VarHandleKeyArrayCommon<Base>::assign(const std::vector<std::string>& vs) {
+    StatusCode sc(StatusCode::SUCCESS);
+    this->clear();
+    for (auto & s : vs) {
+      Base b;
+      if (!b.assign(s)) {
+        sc = StatusCode::FAILURE;
+      } else {
+        // Skip blank keys
+        if (b.key() != "") {
+          this->push_back(b);
+        }
+      }
+    }
+    return sc;
+  }
+  
+  //
+  // string representation of VarHandleKeyArray
+  //
+  template <class Base>
+  inline
+  std::string VarHandleKeyArrayCommon<Base>::toString() const {
+    std::ostringstream ost;
+    typename std::vector<Base>::const_iterator itr;
+    itr = this->begin();
+    size_t sz = this->size();
+    for ( size_t i=0; i < sz; ++i, ++itr) {
+      ost << "'" << itr->storeHandle().name() << "/" 
+          << itr->objKey() << "'";
+      if (i != sz-1) {
+        ost << ",";
+      }
+    }
+    return ost.str();      
+  }
+  
+  //
+  // create array of all base VarHandleKeys in the Array
+  //
+  template <class Base>
+  inline  
+  std::vector<SG::VarHandleKey*> VarHandleKeyArrayCommon<Base>::keys() const {
+    std::vector<SG::VarHandleKey*> keys;
+    typename std::vector<Base>::const_iterator itr;
+    for (itr = this->begin(); itr != this->end(); ++itr) {
+      SG::VarHandleKey* vk = 
+        const_cast<SG::VarHandleKey*>( (const SG::VarHandleKey*) &(*itr) );
+      keys.push_back( vk );
+    }
+    return keys;
+  }      
+  
+}
diff --git a/Control/StoreGate/StoreGate/VarHandleKeyArrayProperty.h b/Control/StoreGate/StoreGate/VarHandleKeyArrayProperty.h
new file mode 100644
index 0000000000000000000000000000000000000000..eaa86d68f6caafe92918dbf36014900dd398b481
--- /dev/null
+++ b/Control/StoreGate/StoreGate/VarHandleKeyArrayProperty.h
@@ -0,0 +1,104 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef STOREGATE_VARHANDLEKEYARRAYPROPERTY
+#define STOREGATE_VARHANDLEKEYARRAYPROPERTY 1
+
+/**
+ * @file StoreGate/VarHandleKeyArrayProperty.h
+ * @author C. Leggett
+ * @date Updated: Jun 17, 2016
+ * @brief class to handle Properties for  VarHandleKeyArray
+ */
+
+#include "StoreGate/VarHandleKeyArray.h"
+#include "StoreGate/ReadHandleKeyArray.h"
+#include "StoreGate/WriteHandleKeyArray.h"
+#include "GaudiKernel/Property.h"
+#include <iostream>
+
+namespace Gaudi { 
+  namespace Parsers {
+    GAUDI_API
+    StatusCode parse(SG::VarHandleKeyArray& v, const std::string& s);    
+  }
+
+  namespace Utils {
+    GAUDI_API
+    std::ostream& toStream(const SG::VarHandleKeyArray& v, std::ostream& o);    
+  }
+}
+
+namespace SG {
+
+  class GAUDI_API VarHandleKeyArrayProperty
+    : public ::Property 
+  {
+  public:
+ 
+    VarHandleKeyArrayProperty( const std::string& name, 
+                               SG::VarHandleKeyArray& ref );
+ 
+    VarHandleKeyArrayProperty& operator=( const SG::VarHandleKeyArray& value );
+ 
+    virtual VarHandleKeyArrayProperty* clone() const override;
+ 
+    virtual bool load( Property& destination ) const override;
+ 
+    virtual bool assign( const Property& source ) override;
+ 
+    virtual std::string toString() const override;
+ 
+    virtual void toStream(std::ostream& out) const override;
+ 
+    virtual StatusCode fromString(const std::string& s) override;
+ 
+    const SG::VarHandleKeyArray& value() const;
+ 
+    bool setValue( const SG::VarHandleKeyArray& value );
+ 
+ 
+  private:
+    /** Pointer to the real property. Reference would be better, 
+     *  but Reflex does not support references yet
+     */
+    SG::VarHandleKeyArray* m_pValue;
+  };
+
+
+} // namespace SG
+
+template<>
+class SimplePropertyRef< SG::VarHandleKeyArray > :
+  public SG::VarHandleKeyArrayProperty
+{
+public:
+  SimplePropertyRef(const std::string& name, SG::VarHandleKeyArray& value) :
+    SG::VarHandleKeyArrayProperty(name, value) {}
+};
+
+
+template<typename T>
+class SimplePropertyRef< SG::ReadHandleKeyArray<T> > :
+  public SG::VarHandleKeyArrayProperty
+{
+public:
+  SimplePropertyRef(const std::string& name, SG::ReadHandleKeyArray<T>& value) :
+    SG::VarHandleKeyArrayProperty(name, value) {}
+};
+
+template<typename T>
+class SimplePropertyRef< SG::WriteHandleKeyArray<T> > :
+  public SG::VarHandleKeyArrayProperty
+{
+public:
+  SimplePropertyRef( const std::string& name, 
+                     SG::WriteHandleKeyArray<T>& value ) :
+    SG::VarHandleKeyArrayProperty(name, value) {}
+};
+
+
+
+
+#endif
diff --git a/Control/StoreGate/StoreGate/WriteHandle.h b/Control/StoreGate/StoreGate/WriteHandle.h
index bf7b11da2d23f89cbb0662e6936a37a21415f7a2..84d99dcff0029135f79bbc4a039540db39eaba0d 100644
--- a/Control/StoreGate/StoreGate/WriteHandle.h
+++ b/Control/StoreGate/StoreGate/WriteHandle.h
@@ -4,7 +4,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: WriteHandle.h 726621 2016-02-27 20:03:45Z ssnyder $
+// $Id: WriteHandle.h 756419 2016-06-21 02:02:43Z ssnyder $
 /**
  * @file StoreGate/WriteHandle.h
  * @author S. Binet, P. Calafiura, scott snyder <snyder@bnl.gov>
@@ -145,7 +145,15 @@ public:
   /**
    * @brief Move operator.
    */
-  WriteHandle& operator=( WriteHandle&& rhs ); 
+  WriteHandle& operator=( WriteHandle&& rhs );
+
+
+  /**
+   * @brief Destructor.
+   *
+   * Lock an aux object if m_lockAuxPending is set.
+   */
+  ~WriteHandle();
 
 
   //************************************************************************
@@ -312,6 +320,24 @@ private:
   record (std::unique_ptr<T> data,
           std::unique_ptr<AUXSTORE> auxstore,
           bool isConst);
+
+
+private:
+  /// If non-null, then we need to lock the associated aux store object
+  /// when we're deleted.
+  ///
+  /// This is set when we record an object along with the associated aux const
+  /// with the const flag set (the default).  Recall that for a const record,
+  /// we want to support the semantics that you can get a non-const pointer
+  /// back from the handle as long as it exists, to finish initialization
+  /// of the object.  For an aux store, though, just getting back a non-const
+  /// pointer is not sufficient, since the store will have been locked
+  /// at the time of the record, preventing changes to the store.
+  ///
+  /// So if we're meant to record a const aux store object, we don't actually
+  /// set it const on the record, but instead set this and do the
+  /// setConst in the destructor.
+  SG::DataProxy* m_lockAuxPending = nullptr;
 }; 
 
 
diff --git a/Control/StoreGate/StoreGate/WriteHandle.icc b/Control/StoreGate/StoreGate/WriteHandle.icc
index 4fa307d6dda9b0a1d0ce7972870e6adf37ce98e6..4b5e3f016dd546982a5b5201173f11973c3b5429 100644
--- a/Control/StoreGate/StoreGate/WriteHandle.icc
+++ b/Control/StoreGate/StoreGate/WriteHandle.icc
@@ -2,7 +2,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: WriteHandle.icc 726840 2016-02-29 16:43:53Z ssnyder $
+// $Id: WriteHandle.icc 756419 2016-06-21 02:02:43Z ssnyder $
 /**
  * @file StoreGate/WriteHandle.icc
  * @author S. Binet, P. Calafiura, scott snyder <snyder@bnl.gov>
@@ -23,6 +23,36 @@
 namespace SG {
 
 
+/**
+ * @brief Helper to temporarily clear aux store association.
+ *
+ * This is used in the object+store version of record, in order to prevent
+ * the store from being locked prematurely.
+ */
+template <class T>
+class SaveStore
+{
+public:
+  SaveStore (T& o)
+    : m_store (o.getStore()),
+      m_o (o)
+  {
+    if (m_store)
+      o.setStore (static_cast<SG::IAuxStore*>(nullptr));
+  }
+
+  ~SaveStore()
+  {
+    if (m_store)
+      m_o.setStore (m_store);
+  }
+
+private:
+  IAuxStore* m_store;
+  T& m_o;
+};
+
+
 //************************************************************************
 // Constructors, etc.
 //
@@ -140,6 +170,20 @@ WriteHandle<T>::operator= (WriteHandle&& h)
 }
 
 
+/**
+ * @brief Destructor.
+ *
+ * Lock an aux object if m_lockAuxPending is true.
+ */
+template <class T>
+WriteHandle<T>::~WriteHandle()
+{
+  if (m_lockAuxPending) {
+    m_lockAuxPending->setConst();
+  }
+}
+
+
 //************************************************************************
 // Deference.  These all return only the cached pointer.
 //
@@ -414,8 +458,12 @@ WriteHandle<T>::record (std::unique_ptr<T> data,
 {
   T& dref = *data;
 
-  if (isConst)
+  if (isConst) {
+    // Temporarily clear the store association, in order to prevent
+    // the aux store from being locked at this point.
+    SaveStore<T> ss (*data);
     CHECK (this->record(std::move(data)));
+  }
   else
     CHECK (this->recordNonConst(std::move(data)));
 
@@ -425,7 +473,7 @@ WriteHandle<T>::record (std::unique_ptr<T> data,
     (SG::asStorable (std::move (auxstore)));
   SG::DataProxy* proxy = m_store->recordObject (std::move(dobj),
                                                 this->name() + "Aux.",
-                                                !m_proxy->isConst(),
+                                                true,
                                                 false);
   if (!proxy) {
     REPORT_ERROR (StatusCode::FAILURE)
@@ -438,6 +486,8 @@ WriteHandle<T>::record (std::unique_ptr<T> data,
     return StatusCode::FAILURE;
   }
 
+  if (m_proxy->isConst())
+    m_lockAuxPending = proxy;
   return StatusCode::SUCCESS;
 }
 
diff --git a/Control/StoreGate/StoreGate/WriteHandleKeyArray.h b/Control/StoreGate/StoreGate/WriteHandleKeyArray.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c051ff88f2f7d552336fadb481b1aa0b4f93ec9
--- /dev/null
+++ b/Control/StoreGate/StoreGate/WriteHandleKeyArray.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef STOREGATE_WRITEHANDLEKEYARRAY_H
+#define STOREGATE_WRITEHANDLEKEYARRAY_H 1
+
+#include "StoreGate/VarHandleKeyArray.h"
+
+#include "StoreGate/WriteHandleKey.h"
+#include "StoreGate/WriteHandle.h"
+
+#include <vector>
+#include <string>
+
+namespace SG {
+
+  /**
+   * @class SG::WriteHandleKeyArray<T>
+   * @brief class to hold an array of WriteHandleKeys
+   *
+   * since it inherits from std::vector, all vector operations are 
+   * permitted.
+   *
+   * initialization can be done in three ways.
+   * 1: with an std::vector<WriteHandleKey> as a parameter
+   *    SG::WriteHandleKeyArray<foo> m_foo ( std::vector<WriteHandleKey> );
+   * 2: with an initializer list of WriteHandleKeys
+   *    SG::WriteHandleKeyArray<foo> m_foo { WriteHandleKey<foo> k1, WriteHandleKey<foo> k2 };
+   * 3: with an initializer list of std::strings, that will be used to
+   *    internally create WriteHandleKeys with those initializers
+   *    SG::WriteHandleKeyArray<foo> m_foo { "key1", "key2", "key3" };
+   */
+
+  template <class T>
+  class WriteHandleKeyArray : public VarHandleKeyArrayCommon< WriteHandleKey<T> > {
+  public:
+    /**
+     * @brief default Constructor from a WriteHandleKeyArray
+     */
+    WriteHandleKeyArray(){};
+
+    /**
+     * @brief Constructor from a WriteHandleKeyArray that takes a vector
+     * of ReaDHandleKeys
+     * @param v vector of WriteHandleKey
+     */
+    WriteHandleKeyArray( const std::vector<WriteHandleKey<T>>& v ) :
+      VarHandleKeyArrayCommon<WriteHandleKey<T>> ( v ) {};
+
+    /**
+     * @brief Constructor from a WriteHandleKeyArray that takes an 
+     * initializer list of WriteHandleKeys
+     * @param l initializer list of WriteHandleKey
+     */
+    WriteHandleKeyArray( std::initializer_list<WriteHandleKey<T>> l ):
+      VarHandleKeyArrayCommon<WriteHandleKey<T>> {l} {};
+
+    /**
+     * @brief Constructor from a WriteHandleKeyArray that takes an 
+     * initializer list of std::strings.
+     * @param l initializer list of std::strings used to create the
+     *          WriteHandleKeys
+     */
+    WriteHandleKeyArray( std::initializer_list<std::string> l ):
+      VarHandleKeyArrayCommon<WriteHandleKey<T>> {l} {};
+
+    /**
+     * @brief return the type (Read/Write/Update) of handle
+     */
+    Gaudi::DataHandle::Mode mode() const { return Gaudi::DataHandle::Writer; }
+
+    /**
+     * @brief create a vector of WriteHandles from the WriteHandleKeys
+     * in the array
+     */
+    std::vector< WriteHandle<T> > makeHandles() const {
+      std::vector< WriteHandle<T> > hndl;
+      typename std::vector<WriteHandleKey<T>>::const_iterator itr;
+      for (itr = this->begin(); itr != this->end(); ++itr) {
+        hndl.push_back ( WriteHandle<T>( *itr) );
+      }
+      return ( std::move( hndl ) );
+    }
+
+  };
+
+
+} // namespace SG
+
+#endif
diff --git a/Control/StoreGate/StoreGate/tools/SGImplSvc.h b/Control/StoreGate/StoreGate/tools/SGImplSvc.h
index 069b569f5e9df89154538f0b42db43ffadbd4b1f..2d94299d728195d31c3d1ea7345246565a49e461 100644
--- a/Control/StoreGate/StoreGate/tools/SGImplSvc.h
+++ b/Control/StoreGate/StoreGate/tools/SGImplSvc.h
@@ -113,7 +113,7 @@ namespace PerfMon { class StorePayloadMon; }
  * @param "FolderNameList" property (default ""): data folders to be created 
  *                                                in this store
  * @author ATLAS Collaboration
- * $Id: SGImplSvc.h 733875 2016-04-04 23:33:03Z leggett $
+ * $Id: SGImplSvc.h 754375 2016-06-13 02:59:46Z ssnyder $
  **/
 class SGImplSvc :
   public Service, 
@@ -501,6 +501,8 @@ public:
 
   /// set store ID. request forwarded to DataStore:
   void setStoreID(StoreID::type id);
+  /// get store ID. request forwarded to DataStore:
+  StoreID::type storeID() const;
 
 
   /** provide list of all storegate keys associated with an object.
@@ -594,6 +596,8 @@ public:
    * @param key The key as which it should be stored.
    * @param allowMods If false, the object will be recorded as const.
    * @param returnExisting If true, return proxy if this key already exists.
+   *                       If the object has been recorded under a different
+   *                       key, then make an alias.
    *
    * Full-blown record.  @c obj should usually be something
    * deriving from @c SG::DataBucket.
diff --git a/Control/StoreGate/src/SGImplSvc.cxx b/Control/StoreGate/src/SGImplSvc.cxx
index dd1016a05a0008d4508799560a6efa9fed1aaec5..f07bad09d215f3ed4dcde21409cc0b792e3834ac 100644
--- a/Control/StoreGate/src/SGImplSvc.cxx
+++ b/Control/StoreGate/src/SGImplSvc.cxx
@@ -56,13 +56,52 @@ using std::hex;
 using std::dec;
 using std::endl;
 using std::ends;
+using std::pair;
 using std::setw;
 using std::string;
+using std::vector;
 
 using SG::DataProxy;
 using SG::DataStore;
 using SG::TransientAddress;
 
+///////////////////////////////////////////////////////////////////////////
+// Find the store id
+
+// return StoreID corresponding to storeNamePrefix. 
+StoreID::type findStoreID(const string& storeNamePrefix) {
+  //vector must be lexically sorted
+  static const vector<pair<string, StoreID::type> > NAMETOID {
+    { "ConditionsStore", StoreID::CONDITION_STORE },
+    { "DetectorStore", StoreID::DETECTOR_STORE },
+    { "EventStore", StoreID::EVENT_STORE },
+    { "InputMetaDataStore", StoreID::METADATA_STORE },
+    { "MetaDataStore", StoreID::SIMPLE_STORE },
+    { "SpareStore", StoreID::SPARE_STORE },
+    { "StoreGateSvc", StoreID::EVENT_STORE },
+    { "TagMetaDataStore", StoreID::METADATA_STORE }
+      };
+  const auto BEG(NAMETOID.begin());
+  const auto END(NAMETOID.end());
+
+  // Account for AthenaMT stores that start with {digits}_
+  size_t ist (0);
+  if (::isdigit(storeNamePrefix.at(0))) {
+    ist = storeNamePrefix.find("_",0) +1;
+  }
+
+  auto i(BEG);
+  while (i != END) {
+    int comp = storeNamePrefix.compare(ist, (i->first).size(), (i->first));
+    //    std::cout << storeNamePrefix <<' '<< storeNamePrefix.size() <<' '<< i->first <<' '<< (i->first).size() <<' '<< comp << std::endl;
+    //NAMETOID is sorted so if we go past storeNamePrefix we are done
+    if (comp < 0) break;
+    else if (comp == 0) return i->second;
+    ++i;
+  }
+  return StoreID::UNKNOWN;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Remapping implementation.
 
@@ -142,47 +181,28 @@ SGImplSvc::~SGImplSvc()  {
 /// Service initialisation
 StatusCode SGImplSvc::initialize()    {
 
-  msg() << MSG::INFO << "Initializing " << name() 
+  msg() << MSG::VERBOSE << "Initializing " << name() 
         << " - package version " << PACKAGE_VERSION << endreq ;
 
+  if(!(Service::initialize()).isSuccess()) {
+    msg() << MSG::ERROR << "Could not initialize base Service !!" << endreq;
+    return StatusCode::FAILURE;
+  }
+
   if (!m_pStore)
     m_pStore = new DataStore (*this);
   if (!m_remap_impl)
     m_remap_impl = new SG::RemapImpl;
 
-  if(!(Service::initialize()).isSuccess()) {
-    msg() << MSG::ERROR << "Could not initialize base Service !!" << endreq;
-    return StatusCode::FAILURE;
-  }
   //properties accessible from now on
   
-  // set store ID (ugly!):
-  string generic_name = name() ;
-  if (generic_name.find("StoreGateSvc")!=std::string::npos || 
-      generic_name.find("EventStore")!=std::string::npos) {
-    store()->setStoreID(StoreID::EVENT_STORE);
-  } else if (generic_name.find("DetectorStore")!=std::string::npos) {
-    store()->setStoreID(StoreID::DETECTOR_STORE);
-  }  else if (generic_name.find("ConditionsStore")!=std::string::npos) {
-    store()->setStoreID(StoreID::CONDITION_STORE);
-  } else if (generic_name.find("InputMetaDataStore")!=std::string::npos ||
-             generic_name.find("TagMetaDataStore")!=std::string::npos) {
-    store()->setStoreID(StoreID::METADATA_STORE);
-  } else if (generic_name.find("MetaDataStore")!=std::string::npos) {
-    store()->setStoreID(StoreID::SIMPLE_STORE);
-  } else if (generic_name.find("SpareStore")!=std::string::npos) {
-    store()->setStoreID(StoreID::SPARE_STORE);
-  } else {
-    store()->setStoreID(StoreID::UNKNOWN);
-  }
+  store()->setStoreID(findStoreID(name()));
   // If this is the default event store (StoreGateSvc), then declare
   // our arena as the default for memory allocations.
-  if (generic_name.find("StoreGateSvc")!=std::string::npos || 
-      generic_name.find("EventStore")!=std::string::npos)
-    {
-      m_arena.makeCurrent();
-      SG::CurrentEventStore::setStore (this);
-    }
+  if (this->storeID() == StoreID::EVENT_STORE) {
+    m_arena.makeCurrent();
+    SG::CurrentEventStore::setStore (this);
+  }
   // set up the incident service:
   if (!(m_pIncSvc.retrieve()).isSuccess()) {
     msg() << MSG::ERROR 
@@ -238,7 +258,7 @@ StatusCode SGImplSvc::initialize()    {
 /// Service start
 StatusCode SGImplSvc::start()    {
 
-  msg() << MSG::INFO << "Start " << name() << endreq;
+  msg() << MSG::VERBOSE << "Start " << name() << endreq;
   /*
   // This will need regFcn clients to be updated first.
   if ( 0 == m_pPPS || (m_pPPS->preLoadProxies(*m_pStore)).isFailure() )
@@ -255,7 +275,7 @@ StatusCode SGImplSvc::start()    {
 /// Service stop
 StatusCode SGImplSvc::stop()    {
 
-  msg() << MSG::INFO << "Stop " << name() << endreq;
+  msg() << MSG::VERBOSE << "Stop " << name() << endreq;
   //HACK ALERT: ID event store objects refer to det store objects
   //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
   // see e.g. https://savannah.cern.ch/bugs/index.php?99993
@@ -264,7 +284,7 @@ StatusCode SGImplSvc::stop()    {
     if (!pISM)
       return StatusCode::FAILURE;
     pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
-    msg() << MSG::INFO << "stop: setting service priority to " << pISM->getPriority(name()) 
+    msg() << MSG::VERBOSE << "stop: setting service priority to " << pISM->getPriority(name()) 
           << " so that event stores get finalized and cleared before other stores" <<endmsg;
   }
   return StatusCode::SUCCESS;
@@ -349,7 +369,7 @@ StatusCode SGImplSvc::clearStore(bool forceRemove)
 //////////////////////////////////////////////////////////////
 /// Service finalisation
 StatusCode SGImplSvc::finalize()    {
-  msg() << MSG::INFO << "Finalizing " << name() 
+  msg() << MSG::VERBOSE << "Finalizing " << name() 
         << " - package version " << PACKAGE_VERSION << endreq ;
   
   // Incident service may not work in finalizea.
@@ -377,7 +397,7 @@ StatusCode SGImplSvc::finalize()    {
 //////////////////////////////////////////////////////////////
 /// Service reinitialization
 StatusCode SGImplSvc::reinitialize()    {
-  msg() << MSG::INFO << "Reinitializing " << name() 
+  msg() << MSG::VERBOSE << "Reinitializing " << name() 
         << " - package version " << PACKAGE_VERSION << endreq ;
   const bool FORCEREMOVE(true);
   clearStore(FORCEREMOVE).ignore();
@@ -558,6 +578,11 @@ void SGImplSvc::setStoreID(StoreID::type id)
 {
   store()->setStoreID(id);
 }
+/// get store id from DataStore:
+StoreID::type SGImplSvc::storeID() const
+{
+  return store()->storeID();
+}
 
 void
 SGImplSvc::keys(const CLID& id, std::vector<std::string>& vkeys, 
@@ -732,11 +757,18 @@ StatusCode SGImplSvc::addToStore (CLID id, SG::DataProxy* proxy)
  * @param obj The data object to store.
  * @param key The key as which it should be stored.
  * @param allowMods If false, the object will be recorded as const.
+ * @param returnExisting If true, return proxy if this key already exists.
+ *                       If the object has been recorded under a different
+ *                       key, then make an alias.
  *
  * Full-blown record.  @c obj should usually be something
  * deriving from @c SG::DataBucket.
  *
  * Returns the proxy for the recorded object; nullptr on failure.
+ * If the requested CLID/key combination already exists in the store,
+ * the behavior is controlled by @c returnExisting.  If true, then
+ * the existing proxy is returned; otherwise, nullptr is returned.
+ * In either case, @c obj is destroyed.
  */
 SG::DataProxy* SGImplSvc::recordObject (SG::DataObjectSharedPtr<DataObject> obj,
                                         const std::string& key,
@@ -754,6 +786,25 @@ SG::DataProxy* SGImplSvc::recordObject (SG::DataObjectSharedPtr<DataObject> obj,
   if (returnExisting) {
     SG::DataProxy* proxy = this->proxy (obj->clID(), key);
     if (proxy) return proxy;
+
+    // Look for the same object recorded under a different key.
+    proxy = this->proxy (raw_ptr);
+    if (proxy) {
+      // Make an alias.
+      if (addAlias (key, proxy).isFailure()) {
+        CLID clid = proxy->clID();
+        std::string clidTypeName; 
+        m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
+        msg() << MSG::WARNING
+              << "SGImplSvc::recordObject: addAlias fails for object "
+              << clid << "[" << clidTypeName << "] " << proxy->name()
+              << " and new key " << key
+              << endreq;
+
+        proxy = nullptr;
+      }
+      return proxy;
+    }
   }
 
   const bool resetOnly = true;
@@ -1019,8 +1070,10 @@ SGImplSvc::record_impl( DataObject* pDObj, const std::string& key,
           << " already in store with key="<< dp->name()
           << ". Will not record a duplicate! "
           << endreq;
-    DataBucketBase* pDBB(dynamic_cast<DataBucketBase*>(pDObj));
-    if (pDBB) pDBB->relinquish(); //don't own the data obj already recorded!
+    if (pDObj != dp->object()) {
+      DataBucketBase* pDBB(dynamic_cast<DataBucketBase*>(pDObj));
+      pDBB->relinquish(); //don't own the data obj already recorded!
+    }
     this->recycle(pDObj);
     return nullptr;
   }
diff --git a/Control/StoreGate/src/StoreGateSvc.cxx b/Control/StoreGate/src/StoreGateSvc.cxx
index bc9d63bf6ba43dd4fedb3de72247e782ef2ee176..70473965c9a801b8bd5fd16ea0fc850e0fd07f0f 100644
--- a/Control/StoreGate/src/StoreGateSvc.cxx
+++ b/Control/StoreGate/src/StoreGateSvc.cxx
@@ -147,7 +147,7 @@ StatusCode StoreGateSvc::initialize()    {
   if(!(Service::initialize()).isSuccess()) return StatusCode::FAILURE;
 
   MsgStream log( messageService(), name() );
-  log << MSG::INFO << "Initializing " << name() 
+  log << MSG::VERBOSE << "Initializing " << name() 
       << " - package version " << PACKAGE_VERSION << endreq ;
 
   // lifted from AlwaysPrivateToolSvc (see Wim comment about lack of global jo svc accessor
@@ -204,7 +204,7 @@ StatusCode StoreGateSvc::initialize()    {
 
 /// Service start
 StatusCode StoreGateSvc::stop()    {
-  msg() << MSG::INFO << "Stop " << name() << endreq;
+  msg() << MSG::VERBOSE << "Stop " << name() << endreq;
   //HACK ALERT: ID event store objects refer to det store objects
   //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
   // see e.g. https://savannah.cern.ch/bugs/index.php?99993
@@ -213,7 +213,7 @@ StatusCode StoreGateSvc::stop()    {
     if (!pISM)
       return StatusCode::FAILURE;
     pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
-    msg() << MSG::INFO << "stop: setting service priority to " << pISM->getPriority(name()) 
+    msg() << MSG::VERBOSE << "stop: setting service priority to " << pISM->getPriority(name()) 
           << " so that event stores get finalized and cleared before other stores" <<endmsg;
   }
   return StatusCode::SUCCESS;
@@ -234,7 +234,7 @@ StatusCode
 StoreGateSvc::finalize() {
   if(!(Service::finalize()).isSuccess()) return StatusCode::FAILURE;
   MsgStream log( messageService(), name() );
-  log << MSG::INFO << "Finalizing " << name() 
+  log << MSG::VERBOSE << "Finalizing " << name() 
       << " - package version " << PACKAGE_VERSION << endreq ;
   if (m_defaultStore) {
     // m_defaultStore is not active, so ServiceManager won't finalize it!
@@ -296,6 +296,8 @@ StatusCode StoreGateSvc::addToStore (CLID id, SG::DataProxy* proxy)
  * @param key The key as which it should be stored.
  * @param allowMods If false, the object will be recorded as const.
  * @param returnExisting If true, return proxy if this key already exists.
+ *                       If the object has been recorded under a different
+ *                       key, then make an alias.
  *
  * Full-blown record.  @c obj should usually be something
  * deriving from @c SG::DataBucket.
@@ -390,6 +392,11 @@ StoreGateSvc::setStoreID(StoreID::type id)
 {
   _SGVOIDCALL(setStoreID,(id));
 }
+StoreID::type 
+StoreGateSvc::storeID() const
+{
+  _SGXCALL(storeID,(),StoreID::UNKNOWN);
+}
 
 void
 StoreGateSvc::keys(const CLID& id, std::vector<std::string>& vkeys, 
@@ -536,5 +543,10 @@ void StoreGateSvc::makeCurrent()
   _SGVOIDCALL (makeCurrent, ());
 }
 
+StatusCode StoreGateSvc::removeProxy(SG::DataProxy* proxy, const void* pTrans, 
+                                     bool forceRemove) {
+  _SGXCALL(removeProxy, (proxy, pTrans, forceRemove), StatusCode::FAILURE);
+}
+
 
 #endif //ATLASHIVE
diff --git a/Control/StoreGate/src/VarHandleKeyArrayProperty.cxx b/Control/StoreGate/src/VarHandleKeyArrayProperty.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c1996368821503aafd1b4e157e5f49b3446b6773
--- /dev/null
+++ b/Control/StoreGate/src/VarHandleKeyArrayProperty.cxx
@@ -0,0 +1,206 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// stl includes
+#include <sstream>
+#include <map>
+#include <boost/tokenizer.hpp>
+
+// StoreGate includes
+#include "StoreGate/VarHandleKeyArrayProperty.h"
+
+namespace Gaudi { 
+  namespace Parsers {
+    
+    
+/**
+ * @brief Gaudi function used to initialize a property from a string.
+ * @param v The object to initialize.
+ * @param s The string from which to initialize.
+ *
+ * Used during Gaudi property handling to set object @c v from the string @c s.
+ * Note that @c s is a representation of the property setting; thus, in the
+ * case of setting a property from a string, @c s will contain quote marks.
+ */
+    StatusCode 
+    GAUDI_API
+    parse(SG::VarHandleKeyArray& v, const std::string& s)
+    {
+      std::vector<std::string> vp;
+      StatusCode sc = Gaudi::Parsers::parse(vp, s);
+      
+      if (sc.isSuccess())
+        sc = v.assign( vp );
+      
+      return sc;
+    }
+    
+  } //> ns Parsers
+
+  namespace Utils {
+    
+    
+/**
+ * @brief Gaudi function used to convert a property to a string.
+ * @param v The object to convert.
+ * @param o Stream to which to do the conversion.
+ *
+ * Used during Gaudi property handling to get a string representation of @c v.
+ * Note that if the representation is a string, it should be surrounded
+ * by quote marks.
+ */
+    std::ostream& 
+    GAUDI_API
+    toStream(const SG::VarHandleKeyArray& v, std::ostream& o)
+    {
+      o << "[" << v.toString() << "]";      
+      return o;
+    }
+    
+  } //> ns Utils
+} //> ns Gaudi
+
+
+namespace SG {
+
+
+/**
+ * @brief Constructor with parameters.
+ * @param name Name of the property.
+ * @param ref Object which this property is setting.
+ */
+  VarHandleKeyArrayProperty::VarHandleKeyArrayProperty( const std::string& name, 
+                                                        SG::VarHandleKeyArray& ref )
+    : Property( name, typeid( SG::VarHandleKeyArray ) ), 
+      m_pValue( &ref ) 
+  {
+}
+
+
+/**
+ * @brief Assignment operator.
+ * @param value Value from which to assign.
+ *
+ * Copy the value object which we control from another value object.
+ */
+VarHandleKeyArrayProperty& 
+VarHandleKeyArrayProperty::operator=( const SG::VarHandleKeyArray& value ) 
+{
+  setValue( value );
+  return *this;
+}
+
+
+/**
+ * @brief Return a new copy of this Property object.
+ *
+ * The new object will be associated with the _same_ value object
+ * as the original.
+ */
+VarHandleKeyArrayProperty* 
+VarHandleKeyArrayProperty::clone() const 
+{
+  return new VarHandleKeyArrayProperty( *this );
+}
+
+
+/**
+ * @brief Set the value of another Property.
+ * @param destination The Property whose value is changed.
+ *
+ * The value object of this Property is copied to that of @c destination
+ * by converting to a string and back again.  Returns true on success,
+ * false on failure.
+ */
+bool
+VarHandleKeyArrayProperty::load( Property& destination ) const 
+{
+  return destination.assign( *this );
+}
+
+
+/**
+ * @brief Set the value of this Property from another.
+ * @param destination The Property from which the value should be copied.
+ *
+ * The value object of this @c source is copied to that of this Property
+ * by converting to a string and back again.  Returns true on success,
+ * false on failure.
+ */
+bool
+VarHandleKeyArrayProperty::assign( const Property& source ) 
+{
+  return fromString( source.toString() ).isSuccess();
+}
+
+
+/**
+ * @brief Return a string representation of the value object.
+ */
+std::string
+VarHandleKeyArrayProperty::toString( ) const 
+{
+  useReadHandler();
+  std::ostringstream o;
+  Gaudi::Utils::toStream(*m_pValue, o);
+  return o.str();
+}
+
+
+/**
+ * @brief Write a string representation of the value object to a stream.
+ * @param out Stream to which to write.
+ */
+void
+VarHandleKeyArrayProperty::toStream(std::ostream& out) const
+{
+  useReadHandler();
+  out << this->toString();
+}
+
+
+/**
+ * @brief Set this value object from a string.
+ * @param s String from which to initialize the value.
+ *
+ * Returns failure if the conversion does not succeed.
+ */
+StatusCode 
+VarHandleKeyArrayProperty::fromString(const std::string& s)
+{
+  if (!Gaudi::Parsers::parse(*m_pValue, s).isSuccess()) {
+    return StatusCode::FAILURE;
+  }
+  return useUpdateHandler()
+    ? StatusCode::SUCCESS
+    : StatusCode::FAILURE;
+}
+
+
+/**
+ * @brief Return the value object for this Property.
+ */
+const SG::VarHandleKeyArray& 
+VarHandleKeyArrayProperty::value() const 
+{
+  useReadHandler();
+  return *m_pValue;
+}
+
+
+/**
+ * @brief Set the value object for this Property.
+ * @param value Value from which to copy.
+ *
+ * Return true on success; false if the update handler failed.
+ */
+bool
+VarHandleKeyArrayProperty::setValue( const SG::VarHandleKeyArray& value ) 
+{
+  m_pValue->operator=(value);
+  return useUpdateHandler();
+}
+
+
+}  // namespace SG
diff --git a/Control/StoreGate/test/SGtests.cxx b/Control/StoreGate/test/SGtests.cxx
index e7fcfd043facde1fa0c822da1ce9e4c69dd79cd6..4013bbc93801afcaab183e702401f799a37f918e 100644
--- a/Control/StoreGate/test/SGtests.cxx
+++ b/Control/StoreGate/test/SGtests.cxx
@@ -50,10 +50,12 @@ using CxxUtils::make_unique;
 class Base {};
 class Foo : public Base {
 public:
+  static std::vector<int> dtor_log;
   Foo() : m_i(0), m_d(0.0) {}
   Foo(int i) : m_i(i), m_d(0.0) {}
   int i() const { return m_i; }
   ~Foo() {
+    dtor_log.push_back (m_i);
 #ifdef MAKEITBOMB
     //int* ifg(0);
     //std::cout << *ifg << std::endl; 
@@ -64,6 +66,7 @@ private:
   int m_i;
   double m_d;
 };
+std::vector<int> Foo::dtor_log;
 class Bar : public Base {};
 class NotThere {};
 
@@ -98,14 +101,16 @@ struct BX
   : public IAuxElement
 {
   int x;
-  BX(int the_x=0) : x(the_x), m_store(0) {}
+  BX(int the_x=0) : x(the_x), m_store(0), m_constStore(nullptr) {}
 
   bool hasStore() const { return m_store != 0; }
   void setStore (SG::IAuxStore* store) { m_store = store; }
+  void setStore (SG::IConstAuxStore* store) { m_constStore = store; }
   bool usingStandaloneStore() const { return hasStore(); }
   SG::IAuxStore* getStore() { return m_store; }
 
   SG::IAuxStore* m_store;
+  SG::IConstAuxStore* m_constStore;
 };
 struct BBX
   : public IAuxElement
@@ -131,9 +136,10 @@ CLASS_DEF( TestVector<BX> , 82735621, 1 )
 CLASS_DEF( TestVector<BBX> , 125040193 , 1 )
 
 class TestAuxStore
-  : public SG::IAuxStore
+  : public SG::IAuxStore, public ILockable
 {
 public:
+  TestAuxStore() : m_locked(false) {}
   virtual const void* getData (SG::auxid_t /*auxid*/) const { return 0; }
   virtual const SG::auxid_set_t& getAuxIDs() const { return m_set; }
   virtual void* getData (auxid_t /*auxid*/, size_t /*size*/, size_t /*capacity*/) { return 0; }
@@ -142,9 +148,12 @@ public:
   virtual void reserve (size_t /*sz*/) {}
   virtual void shift (size_t /*pos*/, ptrdiff_t /*offs*/) {}
   virtual void* getDecoration (auxid_t /*auxid*/, size_t /*size*/, size_t /*capacity*/) { std::abort(); }
-  virtual void lock() { std::abort(); }
+  virtual void lock() { m_locked = true; }
   virtual void clearDecorations() { std::abort(); }
   virtual size_t size() const { std::abort(); }
+
+  bool m_locked;
+
 private:
   SG::auxid_set_t m_set;
 };
@@ -1005,6 +1014,82 @@ namespace Athena_test {
   }
 
 
+  void testRecordObject(StoreGateSvc& rSG)
+  {
+    cout << "\n*** StoreGateSvcClient_test testRecordObject BEGINS ***" << endl;
+    Foo::dtor_log.clear();
+
+    SG::DataObjectSharedPtr<DataObject> obj101 =
+      SG::asStorable (CxxUtils::make_unique<Foo> (101));
+    SG::DataProxy* proxy101 = rSG.recordObject (obj101, "obj101", false, false);
+    assert (proxy101->name() == "obj101");
+    assert (proxy101->object() == obj101.get());
+    assert (obj101->refCount() == 2);
+    assert (proxy101->refCount() == 1);
+    assert (proxy101->isConst());
+
+    SG::DataObjectSharedPtr<DataObject> obj102 =
+      SG::asStorable (CxxUtils::make_unique<Foo> (102));
+    SG::DataProxy* proxy102 = rSG.recordObject (obj102, "obj102", true, false);
+    assert (proxy102->name() == "obj102");
+    assert (proxy102->object() == obj102.get());
+    assert (obj102->refCount() == 2);
+    assert (!proxy102->isConst());
+
+    assert (Foo::dtor_log.empty());
+
+    std::cout << ">>> test duplicate record1\n";
+    SG::DataObjectSharedPtr<DataObject> obj103 =
+      SG::asStorable (CxxUtils::make_unique<Foo> (103));
+    SG::DataProxy* proxy103 = rSG.recordObject (obj103, "obj101", false, false);
+    assert (proxy103 == nullptr);
+    assert (obj103->refCount() == 2); // Held by m_trash
+    std::cout << "<<< test duplicate record1\n";
+
+    SG::DataObjectSharedPtr<DataObject> obj104=
+      SG::asStorable (CxxUtils::make_unique<Foo> (104));
+    SG::DataProxy* proxy104 = rSG.recordObject (obj104, "obj101", false, true);
+    assert (proxy104 == proxy101);
+    assert (obj104->refCount() == 1);
+
+    std::cout << ">>> test duplicate record2\n";
+    SG::DataProxy* proxy999 = rSG.recordObject (obj101, "obj999", false, false);
+    assert (proxy999 == nullptr);
+    assert (obj101->refCount() == 3); // Held by m_trash
+    std::cout << "<<< test duplicate record2\n";
+
+    assert (proxy101->refCount() == 1);
+    proxy999 = rSG.recordObject (obj101, "obj999", false, true);
+    assert (proxy999 == proxy101);
+    assert (proxy101->refCount() == 2);
+    assert (obj101->refCount() == 3);
+
+    rSG.clearStore();
+    assert (obj101->refCount() == 1);
+    assert (obj102->refCount() == 1);
+    assert (obj103->refCount() == 1);
+    assert (obj104->refCount() == 1);
+
+    cout << "\n*** StoreGateSvcClient_test testRecordObject OK ***" << endl;
+  }
+
+
+  void testWriteAux(StoreGateSvc& rSG)
+  {
+    cout << "\n*** StoreGateSvcClient_test testWriteAux BEGINS ***" << endl;
+
+    TestAuxStore* paux = nullptr;
+    {
+      SG::WriteHandle<BX> h ("testWriteAux", rSG.name());
+      auto obj = CxxUtils::make_unique<BX> (10);
+      auto objAux = CxxUtils::make_unique<TestAuxStore>();
+      paux = objAux.get();
+      assert (h.record (std::move(obj), std::move(objAux)).isSuccess());
+      assert (!paux->m_locked);
+    }
+    cout << "\n*** StoreGateSvcClient_test testWriteAux OK ***" << endl;
+  }
+
 } //end namespace
 #endif /*NOGAUDI*/
  
diff --git a/Control/StoreGate/test/WriteHandle_test.cxx b/Control/StoreGate/test/WriteHandle_test.cxx
index 45deff97ca9bf5ccfbd8e0d873f7ebe6e130fe87..c49555a82074d8f3e7b9a71fae016d13a5c5fe02 100644
--- a/Control/StoreGate/test/WriteHandle_test.cxx
+++ b/Control/StoreGate/test/WriteHandle_test.cxx
@@ -30,17 +30,18 @@
 
 
 class MyObjAux
-  : public SG::IConstAuxStore
+  : public SG::IConstAuxStore, public ILockable
 {
 public:
   MyObjAux(int x=0) : x(x) {}
   ~MyObjAux() { deleted.push_back (x); }
   int x;
+  bool m_locked = false;
 
   virtual const void* getData (SG::auxid_t /*auxid*/) const override { return 0; }
   virtual void* getDecoration (SG::auxid_t /*auxid*/, size_t /*size*/, size_t /*capacity*/) override { return 0; }
   virtual const SG::auxid_set_t& getAuxIDs() const override { std::abort(); }
-  virtual void lock() override { }
+  virtual void lock() override { m_locked = true; }
   virtual void clearDecorations() override { }
   virtual size_t size() const override { return 0; }
 
@@ -54,6 +55,7 @@ class MyObj
 public:
   MyObj(int x=0) : x(x) {}
   ~MyObj() { deleted.push_back (x); }
+  SG::IAuxStore* getStore() const { return nullptr; }
   void setStore (SG::IConstAuxStore* store) {aux = dynamic_cast<MyObjAux*>(store); }
   int x;
   MyObjAux* aux {nullptr};
@@ -340,7 +342,7 @@ void test5()
   assert (h4a.isValid());
   assert (h4a.isInitialized());
   assert (h4a->x == 133);
-  assert (h4a.isConst());
+  assert (!h4a.isConst());
 
   MyObj::deleted.clear();
   MyObjAux::deleted.clear();
@@ -365,6 +367,17 @@ void test5()
   assert (h6->aux == nullptr);
   assert (MyObj::deleted == std::vector<int>{});
   assert (MyObjAux::deleted == std::vector<int>{135});
+
+  MyObjAux* paux = nullptr;
+  {
+    SG::WriteHandle<MyObj> h7 ("foo7", "FooSvc");
+    assert (h7.setStore (&testStore).isSuccess());
+    auto ptrs7 = makeWithAux(30);
+    paux = ptrs7.second.get();
+    assert (h7.record (std::move(ptrs7.first), std::move(ptrs7.second)).isSuccess());
+    assert (!paux->m_locked);
+  }
+  assert (paux->m_locked);
 }