【问题标题】:C# How to connect to different databases based on a flagC#如何根据一个标志连接到不同的数据库
【发布时间】:2018-06-05 10:38:24
【问题描述】:

我正在尝试在 C# Webapi 项目中创建一个通用函数,以根据输入标志的值连接到两个数据库之一。每个数据库具有相同的结构,但不同的数据和每次调用将始终使用相同的数据库。

我的其余代码与数据库无关,因此它需要能够使用通用 db 对象,而不是每次调用数据库时都做出决定。

这是我认为可以解决问题的代码:

public static dynamic GetDb(string scope = "dev") {
    dynamic db;

    if (Globals.db == null) {
        switch (scope.ToLower()) {
        case "tns":
            db = new TnsDb();
            break;

        case "sng":
            db = new SngDb();
            break;

        default:
            db = new TnsDb();
            break;
        }

        Globals.db = db;
    } else {
        db = Globals.db;
    }

    return db;
}

我正在使用实体框架,它为我连接到项目的每个数据库创建了一个访问类,并为我需要访问的每个存储过程包含了一个方法。我想做的是让这个通用方法返回一个表示适当数据库类的对象。

我遇到的问题是该方法没有返回可用的对象。我尝试过使用动态的返回类型(如上)、普通对象和 DbContext(实体框架 db 类的父类)以及其他一些出于绝望的东西,但每次调用语句都会收到一个对象实体框架数据库类中没有任何方法。

任何关于如何动态选择和返回保留所有方法的适当对象的想法都将不胜感激,因为我至少可以节省一些头发。

【问题讨论】:

  • 我建议使用存储库模式,它在 db A => web Api 域或 db B 和 webApi 域之间映射。您可以使用 AutoMapper 映射您的域对象。
  • 泛型也很有用
  • 如果数据库相同,那么 DbContext 不就是相同的,只有一个其他连接字符串吗? ...如果不是的话:考虑一个通用接口。
  • @developer 我是 C# 新手,所以我不确定你指的是什么。你能解释一下存储库模式吗?任何代码示例也将不胜感激。
  • @bradbury9 我是 C# 新手,所以我不确定您指的是什么。你能解释一下泛型是什么吗?任何代码示例也将不胜感激。

标签: c# database entity-framework asp.net-web-api2


【解决方案1】:

您提到每个数据库具有相同的结构,但您的函数使用不同的数据库上下文。在这种情况下,您不能使用动态对象来使用动态对象。

由于您的数据库具有相同的结构,您可以在初始化 DbContext 时将连接字符串更改为数据库。如果你真的想使用单独的数据库上下文,那么你应该使用你的函数返回的接口

IMyDatabase
{
BbSet<Model1> Model1{get;set;}
BbSet<Model2> Model2{get;set;}
}
TnsDb:IMyDatabase
{
BbSet<Model1> Model1{get;set;}
BbSet<Model2> Model2{get;set;}
}
SngDb:IMyDatabase
{
BbSet<Model1> Model1{get;set;}
BbSet<Model2> Model2{get;set;}
}

并且你们两个上下文都需要实现这个,那么你的功能可能是这样的

public static IMyDatabase GetDb(string scope = "dev") {
dynamic db;

if (Globals.db == null) {
    switch (scope.ToLower()) {
    case "tns":
        return new TnsDb();

    case "sng":
        return new SngDb();

    default:
        return new TnsDb();
    }
}

但是您不应该使用两个单独的数据库上下文,在您的情况下,使用不同的连接字符串就足够了

虽然为此目的使用静态函数不是很好,但您可以使用依赖注入的一些存储库模式

【讨论】:

  • 这可能行得通,但是当我在 Visual Studio 中连接数据库时,上下文类是自动生成的,这个接口会返回自动生成的类中的所有方法,还是我必须重复它们全部在界面中?我是 C# 新手,所以还不熟悉这种语言的工作原理。
  • 还有什么是Bbset? Visual Studio 无法识别?
  • 看起来像一个类型,应该是DbSet
  • 谢谢@bradbury9。这样可行。我认为这似乎是一个愚蠢的问题,但我是否认为接口应该包含 db 类中的每个方法,或者我可以只使用一个空接口吗?
  • 你想用的所有方法
【解决方案2】:

成功!我最终创建了一个与 db 类具有相同方法的接口,并从通用方法返回。

这是来自界面的sn-p:

public interface IDatabase {
    ObjectResult<Method_1_Result> Method_1(Nullable<int> id, string username);
    ObjectResult<Method_2_Result> Method_2(string username, string password);
}

以下是 db 类的等效方法:

public partial class TnsDb : DbContext, IDatabase {
    public TnsDbDev()
        : base("name=TnsDb")
    {
    }

    public virtual ObjectResult<Method_1_Result> Method_1(Nullable<int> id, string username)
    {
        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Method_1_Result>("Method_1", idParameter, usernameParameter);
    }

    public virtual ObjectResult<Method_2_Result> Method_2(string username, string password)
    {
        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Method_2_Result>("Method_2", usernameParameter, passwordParameter);

    }
}

public partial class SngDb : DbContext, IDatabase {
    public SngDbDev()
        : base("name=SngDb")
    {
    }

    public virtual ObjectResult<Method_1_Result> Method_1(Nullable<int> id, string username)
    {
        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Method_1_Result>("Method_1", idParameter, usernameParameter);
    }

    public virtual ObjectResult<Method_2_Result> Method_2(string username, string password)
    {
        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Method_2_Result>("Method_2", usernameParameter, passwordParameter);

    }
}

请注意,我必须从接口方法中删除 get 和 set 主体,因为它们不需要并且不断产生错误。

我还怀疑此解决方案特定于我需要连接到具有完全相同架构的两个数据库的情况,并且如果架构略有不同,则无法工作,因为它们无法共享相同的接口。

该技术还要求您记住每次重新生成 db 类(在本例中为 TnsDb 类)时重新添加对接口的引用,并在更改任何方法时保持最新db 类。

无论如何,我希望这可以帮助任何与我遇到同样问题的人。感谢所有帮助我解决这个问题的人。

【讨论】:

    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 2023-03-24
    • 2019-05-18
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多