代码之家  ›  专栏  ›  技术社区  ›  cjk

如何检查当前操作是否在对象范围内?

  •  1
  • cjk  · 技术社区  · 16 年前

    类似于在TransactionScope范围内进行的数据库连接的行为,我希望能够在类内测试它是否在另一个类的实例内?

    我的剧本

    我有一个类(EntityBase),所有数据库对象都是基于它构建的,并且有一些方法,如AddToDatabase、UpdateIndDatabase、DeleteFromDatabase。

    我想创建一个Bulkloader类,它将以批量方式处理插入。这将有一个完整的方法,比如TransactionScope类,它将数据加载到数据库中。

    这将需要更改EntityBase类,以便在Bulkloader类的作用域内进行安装并与该类交互时,它的行为有所不同。

    示例代码:

    using (BulkLoader bulk = new BulkLoader(connection, transaction))
    {
        foreach (IToDatabase assignment in assignmentsCollection)
        {
            assignment.WriteToDataBase(connection, transaction);
        }
    
        bulk.Complete();
    }
    
    class ClientAssignment : IToDatabase
    {
         public int WriteToDataBase(IDbConnection connection, 
             IDbTransaction transaction)
         {
              foreach (EntityBase account in accountsCollection)
              {
                    account.AddToDataBase(connection, transaction);
              }
    
              foreach (EntityBase person in personsCollection)
              {
                    person.AddToDataBase(connection, transaction);
              }
         }
    }
    
    class EntityBase
    {
        public virtual int AddToDatabase(IDbConnection connection, 
            IDbTransaction transaction)
        {
            // question relates to this bit
            if (inBulkLoaderClass)
            {
                // interact with bulk loader
            }
            else 
            {
                // do existing code
            }
        }
    }
    
    3 回复  |  直到 16 年前
        1
  •  4
  •   Jon Skeet    16 年前

    你可以使用 ThreadStaticAttribute :

    public class BulkLoader : IDisposable
    {
        [ThreadStatic]
        private static BulkLoader currentBulkLoader;
    
        public BulkLoader()
        {
            if (InBulkLoader)
            {
                throw new InvalidOperationException();
            }
            currentBulkLoader = this;
        }
    
        public void Dispose()
        {
            currentBulkLoader = null;
        }
    
        public static bool InBulkLoader
        {
             get { return currentBulkLoader != null; }
        }
    
        public static BulkLoader CurrentBulkLoader
        {
             get { return currentBulkLoader; }
        }
    }
    

    我一般不喜欢线程静态,但我认为在这种情况下可能没问题。签入构造函数确保您永远不会进入“嵌套的”批量加载程序。如果你 希望 为了能够嵌套它们,请改为保留一个计数器(构造函数中递增,释放调用中递减)。

        2
  •  1
  •   Marc Gravell    16 年前

    嗯,您可以对环境对象(特别是线程静态字段)执行一些操作,但它并不漂亮。我认为,如果逻辑不同,首先它应该是一个独立的方法。另外,请注意,有一种观点认为实体对象无论如何都不应该与数据库通信——它们的工作是表示对象的状态;担心持久性是存储库类(或类似类)的工作。然后,您的存储库将有两个策略来处理事情。可能有一个IBolkRepository接口,repo可以(可选)实现,等等。

        3
  •  0
  •   Kunal S    16 年前

    我同意马克的观点。我们也采用了马克所展示的几乎相同的方法。我想这是解决这个问题的标准和最佳方法。虽然我对这里的线程静态业务不太熟悉,但不能提出更多的建议。

    推荐文章