如何避免存储库重复代码

发布于 2024-11-06 08:45:28 字数 988 浏览 0 评论 0原文

我已经成功设置了一个列出团队的简单 mvc 应用程序。我正在使用 Ninject 根据控制器注入适当的存储库(感谢堆栈溢出;)。一切看起来都不错,除了存储库代码看起来完全相同。我知道这是错误的。所以我的 TeamRepository 有两个类(目前)。

public class SwimTeamRepository : ITeamRepository<SwimTeam> 
{
    private readonly Table<SwimTeam> _teamTable;
    public SwimTeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<SwimTeam>());
    }

    public IQueryable<SwimTeam> Team
    {
        get { return _teamTable; }
    }
}

public class SoccerTeamRepository : ITeamRepository<SoccerTeam>
{
    private readonly Table<SoccerTeam> _teamTable;
    public SoccerTeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<SoccerTeam>());
    }

    public IQueryable<SoccerTeam> Team
    {
        get { return _teamTable; }
    }
}

除了类和表名称之外,它们看起来完全相同,因此显然我需要重新考虑这一点。这里最好的方法是什么?辛格尔顿?工厂方法?

提前致谢!

I have successfully setup a simple mvc application that lists teams. I'm using Ninject to inject the appropriate repository depending on the controller (thanks to stack overflow ;). All looks good, except that the repository code looks exactly the same. And I know that's wrong. So my TeamRepository has two classes (for now).

public class SwimTeamRepository : ITeamRepository<SwimTeam> 
{
    private readonly Table<SwimTeam> _teamTable;
    public SwimTeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<SwimTeam>());
    }

    public IQueryable<SwimTeam> Team
    {
        get { return _teamTable; }
    }
}

public class SoccerTeamRepository : ITeamRepository<SoccerTeam>
{
    private readonly Table<SoccerTeam> _teamTable;
    public SoccerTeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<SoccerTeam>());
    }

    public IQueryable<SoccerTeam> Team
    {
        get { return _teamTable; }
    }
}

They look exactly the same except for the Class and Table name, so clearly I need to re-factor this. What would be the best approach here? Singleton? Factory Method?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

路弥 2024-11-13 08:45:28

你可以使用泛型:

public interface ITeamRepository<T>
{
}

public class TeamRepository<TTeam> : ITeamRepository<TTeam>
    where TTeam : Team
{
    private readonly Table<TTeam> _teamTable;
    public TeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<TTeam>());
    }

    public IQueryable<TTeam> Team
    {
        get { return _teamTable; }
    }
}

public class Team
{
}

public class SwimTeam : Team
{
}

然后像这样使用它...

public void MyMethod()
{
    var repository = new TeamRepository<SwimTeam>();
}

...并像这样设置你的 IoC 容器 w/ Ninject ...

public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<ITeamRepository<SwimTeam>>
            .To<TeamRepository<SwimTeam>>();
    }
}

public void MyMethod()
{    
    var repository = kernel.Get<ITeamRepository<SwimTeam>>();
}

如果你想获得真正的泛型并为所有映射的类拥有一个存储库,你可以做这样的事情:

public interface IRepository
{
    IQueryable<T> Get<T>() where T : class, new();
}

public class Repository : IRepository, IDisposable
{
    private DataContext _dataContext;
    public Repository(string connectionString)
    {
        _dataContext = new DataContext(connectionString);
    }

    public IQueryable<T> Get<T>()
        where T : class, new()
    {
        return _dataContext.GetTable<T>().AsQueryable();
    }

    public void Dispose()
    {
        if (_dataContext != null)
        {
            _dataContext.Dispose();
            _dataContext = null;
        }
    }
}

...您可以像这样调用(在设置 Ninject 容器之后)...

using (var repository = kernel.Get<IRepository>())
{
    var swimTeam = repository.Get<SwimTeam>();
}

由于 Ninject 负责对象的生命周期管理,因此您不必将存储库包装在一个 using 语句。事实上,如果您计划在存储库的生命周期内多次使用该存储库,那么您根本不想在那里使用 using 语句。当它的生命周期结束时,Ninject 会自动处理它。

这是 Rob Conery 撰写的关于使用这种类型的好文章减少使用不同 ORM 的摩擦的技术。

keeg 编辑:

我认为

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : Team {}

应该是,

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : class {}

如果我错了,请纠正。

You could use generics:

public interface ITeamRepository<T>
{
}

public class TeamRepository<TTeam> : ITeamRepository<TTeam>
    where TTeam : Team
{
    private readonly Table<TTeam> _teamTable;
    public TeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<TTeam>());
    }

    public IQueryable<TTeam> Team
    {
        get { return _teamTable; }
    }
}

public class Team
{
}

public class SwimTeam : Team
{
}

Then use it like so...

public void MyMethod()
{
    var repository = new TeamRepository<SwimTeam>();
}

...and set up your IoC container w/ Ninject like so...

public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<ITeamRepository<SwimTeam>>
            .To<TeamRepository<SwimTeam>>();
    }
}

public void MyMethod()
{    
    var repository = kernel.Get<ITeamRepository<SwimTeam>>();
}

If you want to get REAL generic and have a single repository for ALL of your mapped classes, you can do something like this:

public interface IRepository
{
    IQueryable<T> Get<T>() where T : class, new();
}

public class Repository : IRepository, IDisposable
{
    private DataContext _dataContext;
    public Repository(string connectionString)
    {
        _dataContext = new DataContext(connectionString);
    }

    public IQueryable<T> Get<T>()
        where T : class, new()
    {
        return _dataContext.GetTable<T>().AsQueryable();
    }

    public void Dispose()
    {
        if (_dataContext != null)
        {
            _dataContext.Dispose();
            _dataContext = null;
        }
    }
}

...which you could call like so (after setting up your Ninject container)...

using (var repository = kernel.Get<IRepository>())
{
    var swimTeam = repository.Get<SwimTeam>();
}

Since Ninject takes care of the life-cycle management of your objects, you don't HAVE to wrap the repository in a using statement. In fact, you don't want to use a using statement there at all if you plan to use the repository more than once within the scope of its lifetime. Ninject will automatically dispose of it when it's life-cycle ends.

Here's a good article by Rob Conery on using this kind of technique to reduce the friction of using different ORMs.

EDIT by keeg:

I Think

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : Team {}

Should be

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : class {}

Please correct if I'm wrong.

时光是把杀猪刀 2024-11-13 08:45:28

这是你想要的吗?

public class TeamRepository : ITeamRepository<T> 
    {
        private readonly Table<T> _teamTable;
        public TeamRepository(string connectionString)
        {
            _teamTable = (new DataContext(connectionString).GetTable<T>());
        }

        public IQueryable<T> Team
        {
            get { return _teamTable; }
        }
    }

Is this what you want?

public class TeamRepository : ITeamRepository<T> 
    {
        private readonly Table<T> _teamTable;
        public TeamRepository(string connectionString)
        {
            _teamTable = (new DataContext(connectionString).GetTable<T>());
        }

        public IQueryable<T> Team
        {
            get { return _teamTable; }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文