【问题标题】:Linq to SQL database context managementLinq to SQL 数据库上下文管理
【发布时间】:2019-12-12 12:22:10
【问题描述】:

我有一个关于管理 LINQ to SQL 数据库上下文的生命周期的问题。目前,我正在使用工厂在需要时实例化一个新的数据库上下文。在某些情况下这很好,但在其他情况下则不然。例如,当一个操作跨越多个方法时,在每个方法中我都调用工厂来生成一个新实例,而我确实需要在操作的生命周期内在方法之间共享上下文。理论上,操作需要是原子的。所以,我的问题是想知道在工厂中有多个工厂方法来在需要的时候获取所需的上下文是否是一个好的设计?

我在下面提供了一个示例实现。

// 接口

public interface IEntityContextFactory : ISingletonService
{
    IDbContext CreateContext();

    IDbContext GetContext();
}

//工厂类

public class EntityContextFactory : IEntityContextFactory
{
    private IDbContext _context;

    public IDbContext CreateContext()
    {
        var defaultConnectionString = ConfigurationManager.ConnectionStrings["connection_name"].ConnectionString;
        var database = new DataContext(defaultConnectionString);
        // this is a wrapper around the linq to sql context
        return new DbContext(database);
    }

    public IDbContext GetContext()
    {
        // TODO: make threadsafe
        if(_context == null)
        {
            _context = CreateContext();
            return _context;
        }

        return _context;
    }
}

【问题讨论】:

    标签: c# linq-to-sql datacontext


    【解决方案1】:

    在您的方法中,这看起来像是 Dependency Injection 的工作。

    一个需要上下文的方法应该接收一个上下文,而不是接收“更新”它自己的能力——即使是从一个看起来在做同样事情的工厂。

    如果方法可以合理地组织到一个类中,那么该类的构造函数可以要求使用上下文。

    最后,这是真正重要的部分,听起来您想将需要相同上下文的方法封装在一个可以利用您的工厂的新方法(或多个方法)中。

    一个草率的例子。

    public class DataAccess {
    
        private IDbContext _dbContext;
    
        public DataAccess(IDbContext context) {
            _dbContext = context;
        }
    
        // atomic example
        public UserModel GetUser(int id) {
            return _dbContext.UserTable
                .Where(x => x.Id == id)
                .FirstOrDefault();
        }
    
        // not-atomic example
        public bool RecordUserActivity(UserModel user, IEnumerable<UserActivity> activities) {
            try {
                _dbContext.BeginTransaction();
    
                // messy example
                _dbContext.UserLogins
                    .Add(activities.Where(x => x.ActivityType == ActivityTypes.Logins));
                _dbContext.UserEdits
                    .Add(activities.Where(x => x.ActivityType == ActivityTypes.Edits));
                // 
    
                _dbContext.CommitTransaction();
                return true;
    
            } catch (Exception ex) {
                // log your exceptions!
                _dbContext.RollbackTransaction();
            }
            return false;
        }
    }
    

    【讨论】:

    • 感谢@clarkitect 的回复。目前,我将工厂注入到类中,并且类中的方法可以通过工厂请求上下文。但是您提出的建议是注入上下文本身。明白这将解决根本问题,但这条线索不会在任何地方共享同一个实例吗?
    猜你喜欢
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    相关资源
    最近更新 更多