如何重构三个仅通过方法调用不同的数据库操作?

时间:2009-12-20 11:37:33

标签: c# nhibernate refactoring transactions

我有三个数据库操作,如下所示:

public void Add<T>(T entity)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable) entity)
            {
                Session.Save(item);
            }
        }
        else
        {
            Session.Save(entity);
        }

        transaction.Commit();
    }
}

public void Update<T>(T entity)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable) entity)
            {
                Session.Update(item);
            }
        }
        else
        {
            Session.Update(entity);
        }

        transaction.Commit();
    }
}

public void Delete<T>(T entity)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable)entity)
            {
                Session.Delete(item);
            }
        }
        else
        {
            Session.Delete(entity);
        }

        transaction.Commit();
    }
}

正如您所看到的,唯一不同的是Session.[something]部分。我如何将其重构为一种方法呢?

3 个答案:

答案 0 :(得分:0)

您可以创建一个方法,并让它接受委托作为参数,指定您要执行的操作。

private void DatabaseAction<T>(T entity, Action<T> action) 
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable)
        {
            foreach (var item in (IEnumerable) entity)
            {
                action(item);
            }
        }
        else
        {
            action(item);
        }

        transaction.Commit();
    }
}

然后将您的3种方法重构为:

public void Add<T>(T entity)
{
    DatabaseAction(entity, item => Session.Save(item));
}

public void Update<T>(T entity)
{
    DatabaseAction(entity, item => Session.Update(item));
}

public void Delete<T>(T entity)
{
    DatabaseAction(entity, item => Session.Delete(item));
}

答案 1 :(得分:0)

您可以传入应为该实体执行的Action<T>

public static void DoInTransaction<T>(this T entity, Action<T> action)
{
    using (var transaction = Session.BeginTransaction())
    {
        if (entity is IEnumerable<T>)
        {
            foreach (T item in (IEnumerable<T>) entity)
            {
                action(item);
            }
        }
        else
        {
            action(entity);
        }

        transaction.Commit();
    }
}

示例:

entity.DoInTransaction(Session.Save);
entity.DoInTransaction(Session.Update);
entity.DoInTransaction(Session.Delete);

答案 2 :(得分:0)

代表们在这里看起来是一个很好的解决方案,正如其他回答者所解释的那样。可以说可以简化内部逻辑的另一种可能的重构是返回IEnumerable的函数。如果传入的对象是IEnumerable,只需返回它;否则使用传入的对象构建单元素枚举并返回枚举。这会改变这个:

if (entity is IEnumerable)
{
    foreach (var item in (IEnumerable) entity)
    {
       Session.Save(item);
    }
}
else
{
    Session.Save(entity);
}

进入这个:

foreach (var item in ForceEnumerable(entity))
    {
       Session.Save(item);
    }