Ticket Q404917
Visible to All Users

OracleConnection does not support parallel transactions

created 13 years ago

Hello,

i'm using xpo to connect to an oracle database and execute some queries. I'm getting this error "OracleConnection does not support parallel transactions".

Here it is the xpo helper for oracle that i'm using

public static class XpoHelperOracle
{
private static string _connectionStringOracle = "XpoProvider=Oracle;Data Source=192.168.0.101/XE;User ID=myuser;Password=mypass
";

public static Session GetNewSession()
{
return new Session(DataLayer);
}

public static UnitOfWork GetNewUnitOfWork()
{
return new UnitOfWork(DataLayer);
}

private readonly static object lockObject = new object();

static IDataLayer fDataLayer;
static IDataLayer DataLayer
{
get
{
if (fDataLayer == null)
{
lock (lockObject)
{
fDataLayer = GetDataLayer();
}
}
return fDataLayer;
}
}

private static IDataLayer GetDataLayer()
{
// set XpoDefault.Session to null to prevent accidental use of XPO default session
// Se commento il session = null, allora non mi funziona il cambio nome colonna per le tabelle intermedie
//XpoDefault.Session = null;

XPDictionary dictionary = new ReflectionDictionary();

// initialize the XPO dictionary
dictionary.GetDataStoreSchema(typeof(Preordine).Assembly);//Basta solo una classe per assembly Q279523

//XpoDefault.ConnectionString = _connectionString;//da errore

IDataStore store = XpoDefault.GetConnectionProvider(_connectionStringOracle, AutoCreateOption.SchemaAlreadyExists);//oracle

// create a ThreadSafeDataLayer
IDataLayer dl = new ThreadSafeDataLayer(dictionary, store);

return dl;
}
}

any idea why this happen? thank you.
Note that i'm using xpo on a aspnet webpage.

Show previous comments (1)

    Hi,
    the situation is unclear to mee too, becuase this error occur rarely. As i have understood the error is shown when a user is executing a query on oracle server and another one attempt at the same time to execute the same query(or another one).
    From research i have done over internet, it seems that, the oracle version i'm using does not not support parallel transaction that's why xpo shows me the error. A solution could be to open new connections and execute the query but how to do that?

      …how to do that with xpo?
      ps: I think 500 char for a comment are not sufficient.
      Thank you

      DevExpress Support Team 13 years ago

        This error may occur if a new transaction is started while another transaction is in progress. However, in our code we serialize queries and lock the provider while a query is being processed. Possibly, you are manually managing transactions in an inappropriate manner. Please elaborate more on what you are doing in your application and how. A small sample project reproducing the issue would be helpful.

        Answers

        created 13 years ago (modified 13 years ago)

        I'm not manually manging transaction.
        What i'm doing is cloning some xpo object from one session to another.
        Basically when a user click on save, i have to move some rows from SQL Server to Oracle.

        here is the code i'm using:

        Session SqlSession = XpoDataSourcePreordini.Session;// session from the grid
        Session oracleSession = XpoHelperOracle.GetNewSession();

        XPClassInfo preordineClass = SqlSession.GetClassInfo(typeof(Preordine));
        ICollection preordini = SqlSession.GetObjects(preordineClass, CriteriaOperator.Parse(Filter), null, int.MaxValue, false, true);

        CloneIXPSimpleObjectHelper cloneHelper = new CloneIXPSimpleObjectHelper(SqlSession, oracleSession);
        foreach (Preordine currOrdine in preordini)
        {
        Preordine pers = cloneHelper.Clone(currOrdine);
        pers.ID_PREORDINE = currOrdine.ID_PREORDINE;
        oracleSession.Save(pers);
        }

        foreach (Preordine currOrdine in preordini)
        currOrdine.Delete();

        // If i will not execute the following 2 lines of code that i get ORA-12516
        oracleSession.Disconnect();
        oracleSession.Dispose();

        Here it is the class "Preordine" which represent a row moving from sql to oracle

        [Persistent("PREORDINE_CLIENTE")]
        public class Preordine : XPLiteObject
        {
        int fID_PREORDINE;
        [Key(false)]
        public int ID_PREORDINE
        {
        get { return fID_PREORDINE; }
        set { SetPropertyValue<int>("ID_PREORDINE", ref fID_PREORDINE, value); }
        }

        int fNUMPOS;
        public int NUMPOS
        {
        get { return fNUMPOS; }
        set { SetPropertyValue<int>("NUMPOS", ref fNUMPOS, value); }
        }

        String fCOD_CLIENTE;
        [Size(6)]
        public String COD_CLIENTE
        {
        get { return fCOD_CLIENTE; }
        set { SetPropertyValue<String>("COD_CLIENTE", ref fCOD_CLIENTE, value); }
        }

        //…other properties here

        // ctors
        public Preordine(Session session) : base(session) { }
        public Preordine() : base(Session.DefaultSession) { }
        public override void AfterConstruction() { base.AfterConstruction(); }
        }

        here it is the class that clones the instances(from your kb)

        public class CloneIXPSimpleObjectHelper
        {
        /// <summary>
        /// A dictionary containing objects from the source session as key and objects from the
        /// target session as values
        /// </summary>
        /// <returns></returns>
        Dictionary<object, object> clonedObjects;
        Session sourceSession;
        Session targetSession;

        /// <summary>
        /// Initializes a new instance of the CloneIXPSimpleObjectHelper class.
        /// </summary>
        public CloneIXPSimpleObjectHelper(Session source, Session target)
        {
        this.clonedObjects = new Dictionary<object, object>();
        this.sourceSession = source;
        this.targetSession = target;
        }

        public T Clone<T>(T source) where T : IXPSimpleObject
        {
        return Clone<T>(source, targetSession, false);
        }
        public T Clone<T>(T source, bool synchronize) where T : IXPSimpleObject
        {
        return (T)Clone(source as IXPSimpleObject, targetSession, synchronize);
        }

        public object Clone(IXPSimpleObject source)
        {
        return Clone(source, targetSession, false);
        }
        public object Clone(IXPSimpleObject source, bool synchronize)
        {
        return Clone(source, targetSession, synchronize);
        }

        public T Clone<T>(T source, Session targetSession, bool synchronize) where T : IXPSimpleObject
        {
        return (T)Clone(source as IXPSimpleObject, targetSession, synchronize);
        }

        /// <summary>
        /// Clones and / or synchronizes the given IXPSimpleObject.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="targetSession"></param>
        /// <param name="synchronize">If set to true, reference properties are only cloned in case
        /// the reference object does not exist in the targetsession. Otherwise the exising object will be
        /// reused and synchronized with the source. Set this property to false when knowing at forehand
        /// that the targetSession will not contain any of the objects of the source.</param>
        /// <returns></returns>
        public object Clone(IXPSimpleObject source, Session targetSession, bool synchronize)
        {
        if (source == null)
        return null;
        if (clonedObjects.ContainsKey(source))
        return clonedObjects[source];
        XPClassInfo targetClassInfo = targetSession.GetClassInfo(source.GetType());
        object clone = null;
        if (synchronize)
        clone = targetSession.GetObjectByKey(targetClassInfo, source.Session.GetKeyValue(source));
        if (clone == null)
        clone = targetClassInfo.CreateNewObject(targetSession);
        clonedObjects.Add(source, clone);

        foreach (XPMemberInfo m in targetClassInfo.PersistentProperties)
        {
        if (m is DevExpress.Xpo.Metadata.Helpers.ServiceField || m.IsKey)
        continue;
        object val;
        if (m.ReferenceType != null)
        {
        object createdByClone = m.GetValue(clone);
        if ((createdByClone != null) && synchronize == false)
        val = createdByClone;
        else
        {
        val = Clone((IXPSimpleObject)m.GetValue(source), targetSession, synchronize);
        }

        }
        else
        {
        val = m.GetValue(source);
        }
        m.SetValue(clone, val);
        }
        foreach (XPMemberInfo m in targetClassInfo.CollectionProperties)
        {
        if (m.HasAttribute(typeof(AggregatedAttribute)))
        {
        XPBaseCollection col = (XPBaseCollection)m.GetValue(clone);
        XPBaseCollection colSource = (XPBaseCollection)m.GetValue(source);
        foreach (IXPSimpleObject obj in new ArrayList(colSource))
        col.BaseAdd(Clone(obj, targetSession, synchronize));
        }
        }
        return clone;
        }
        }

          Show previous comments (3)

            I have slightly modified the property DataLayer of the XpoOracleHelper to the following one
            lock (lockObject)
                            {
                                return GetDataLayer();
                            }
            and it seems faster than using a cached datalayer

              but i dont know if this could fix the error.

              DevExpress Support Team 13 years ago

                Wrapping the GetDataLayer method call within the lock statement won't lock data layer operations and cannot help in improving performance. I suggest that you use connection pooling to improve XPO performance in a multi-threaded application. Specifically, use the XpoDefault.GetConnectionPoolString method to create a connection string with pooling.
                However, the source of your issue is still unclear to us, and I do not know whether this approach will help you solve it or not.

                Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

                Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.