简体   繁体   English

我可以在 MVC 中的两个不同数据上下文之间重用一个方法吗?

[英]Can I reuse a method between two different data contexts in MVC?

In my organization there are three different groups using three different databases.在我的组织中,三个不同的组使用三个不同的数据库。 The schema of the databases are the same -- same table structure, relational logic, etc -- and the three groups need me to report on their data in my application in the same way.数据库的架构是相同的——相同的表结构、关系逻辑等——这三个组需要我以相同的方式在我的应用程序中报告他们的数据。

I understand that in my application I need to create a separate data context for each database, and in my repositories I need to explicitly declare the data context(s) used by that repository.我知道在我的应用程序中,我需要为每个数据库创建一个单独的数据上下文,并且在我的存储库中,我需要明确声明该存储库使用的数据上下文。 I'm fine with all of that.我对这一切都很好。

But if all three repos need to run the same given method, just against different data contexts, do I really need to write the same method three times?但是,如果所有三个 repos 都需要运行相同的给定方法,只是针对不同的数据上下文,我真的需要编写相同的方法三次吗? Is there no way that I can put my method in a class library, say, or some other fourth file, and then run the method against the context I need to use as and when?有没有办法我可以将我的方法放在类库或其他第四个文件中,然后针对我需要使用的上下文运行该方法?

For example, my repo looks like this:例如,我的仓库如下所示:

public interface IMyRepo
{
    List<string> GetMyData();
}

public class MyRepo : IMyRepo
{
    private readonly ContextA _context;

    public MyRepo(ContextA context) {
        _context = context;
    }

    public List<string> GetMyData()
    {
        //code to get my data and return it
    }
}

Now remember that because of the way my org's database is setup, I need to write this repo three times, once for each group.现在请记住,由于我的组织数据库的设置方式,我需要编写此 repo 三次,每个组一次。 All that changes is the context.改变的只是上下文。

I'd like to take the actual code for method GetMyData() and move it to a fourth file, then just link my repo to that file and call the method through an object reference, passing the context as a parameter, say.我想获取方法 GetMyData() 的实际代码并将其移动到第四个文件,然后将我的 repo 链接到该文件并通过对象引用调用该方法,例如将上下文作为参数传递。 So I could call GetMyData() from my repo above like this:所以我可以像这样从上面的仓库中调用 GetMyData() :

    //method call in my context above
    public List<string> GetMyData()
    {
        //call actual GetMyData() method in my linked file
        return linkedFile.GetMyData(_context);
    }

Is something even remotely like I describe possible?像我描述的那样遥不可及吗?

EDIT: I was asked by @RStevoUK to provide a code example for the linked file I describe, so I'll try to explain here.编辑:@RStevoUK 要求我为我描述的链接文件提供一个代码示例,所以我将在这里尝试解释。 So in my context I have the method GetMyData(), which runs certain code and returns a list object.所以在我的上下文中,我有方法 GetMyData(),它运行某些代码并返回一个列表对象。 In the .NET Framework days, I could put the actual code for GetMyData() into a separate class file, and then pass in the ConnectionString object that the method would use to connect to the correct database and retrieve its data.在 .NET Framework 时代,我可以将 GetMyData() 的实际代码放入单独的类文件中,然后传入 ConnectionString 对象,该方法将使用该对象连接到正确的数据库并检索其数据。

CLASS:班级:

public class ExternalClassFile
{
    public List<string> GetMyData(string connectionString)
    {
        using (SqlConnection connectionString)
        {
            //code to get my data and return it
        }
    }
}

Then, to run this method against a given database, all I would need to do is call an instance of the class, and invoke the method with the correct connection string:然后,要针对给定的数据库运行此方法,我需要做的就是调用该类的一个实例,并使用正确的连接字符串调用该方法:

ExternalClassFile ecf = new ExternalClassFile();

public List<string> CallSharedMethod()
{
    string connection = \\connecting string code;

    return ecf.GetMyData(connection);
}

I don't think I can do that with MVC;我不认为我可以用 MVC 做到这一点。 what I understand of it leads me to believe I can't.我对它的理解使我相信我做不到。 Also, I don't think Generics are what I want, since GetMyData() would contain an actual linq query另外,我不认为泛型是我想要的,因为 GetMyData() 将包含一个实际的 linq 查询

var data = (from d in _context.DatabaseTable_Model
             select d).ToList();

for example.例如。 That "_context" variable references my datacontext, and that's all that changes.那个“_context”变量引用了我的数据上下文,这就是所有的变化。

I've tried to setup a "_context" variable using a "var" declaration instead of a specific context name, but MVC doesn't like that.我尝试使用“var”声明而不是特定的上下文名称来设置“_context”变量,但 MVC 不喜欢这样。 Is there something else I can try that would make the above linq example reusable among multiple contexts?还有什么我可以尝试的方法可以使上述 linq 示例在多个上下文中可重用吗?

I hope this makes more sense.我希望这更有意义。

What I'm hearing is that the only difference between your three repositories would be the specific type of DbContext that gets injected into them.我听到的是,您的三个存储库之间的唯一区别是注入它们的 DbContext 的特定类型。 And the only reason you're stuck being tightly coupled to a given type is that you have code accessing a property on that type, like _context.DatabaseTable_Model .你被困在与给定类型紧密耦合的唯一原因是你有代码访问该类型的属性,比如_context.DatabaseTable_Model

You can typically rewrite your data access code to rely on DbSet<> instead of a specific DbContext type.您通常可以重写数据访问代码以依赖DbSet<>而不是特定的DbContext类型。 And you can get a generic DbSet<> off of any DbContext by calling its DbContext.Set<>() method .您可以通过调用DbContext.Set<>()方法任何DbContext中获取通用DbSet<>

var baseQuery = var data = _context.Set<DatabaseTable_Model>();
var data = (from d in baseQuery
             select d).ToList();

Then you can make your repo take any type of DbContext:然后你可以让你的 repo 采用任何类型的 DbContext:

    private readonly DbContext _context;

    public MyRepo(DbContext context) {
        _context = context;
    }

However , it's worth challenging the assumption that you need three separate data context types in the first place.但是,首先需要三个单独的数据上下文类型的假设是值得挑战的。 If the schemas of the databases are literally the same, then the only difference between these classes should be their name, right?如果数据库的模式实际上是相同的,那么这些类之间的唯一区别应该是它们的名称,对吧? And the only reason the name matters is because DbContext 's default constructor uses naming conventions to decide how to find the connection string to use.名称重要的唯一原因是因为DbContext默认构造函数使用命名约定来决定如何查找要使用的连接字符串。

DbContext has other constructors, though, so if you make your context class use one of those other constructors it should be perfectly possible to construct separate instances of the same class pointing at different databases by passing in the name of the connection string (or the actual connection string, or the connection itself) that you want it to use.但是,DbContext 有其他构造函数,因此,如果您让上下文类使用其他构造函数之一,那么通过传入连接字符串的名称(或实际的您希望它使用的连接字符串或连接本身)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM