Click here to Skip to main content
15,886,761 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello,

I created a monitor system for our cloud environments.

The environments are individual sites with their own database. Since each site has several tasks running, we need to intercept when a task fails. There are other things I monitor but the idea is the same.

The situation is as follows:

I have my monitoring website (ASP.NET Core + EF Core) which gets its data from a database on the database server. This database performs scheduled stored procedures which capture the different things I want to monitor from all databases on the server.

This works well and quickly. My first version I performed a cursor on all databases with each web request, so that was not too efficient.

The problem I face now is that we are integrating new database servers, each with new environments pointing to it.

I would like to avoid creating a new monitor site for each new database server.

On my new version of the monitor I would like to query each server on the single database that stores the different errors for the environments on that server.

What I did so far is to created multiple DbContext classes pointing to their respective database server and 'error' database but share the same entities.

To retrieve my info I perform the same exact LINQ query on all DbContext and combine the results before displaying them.

Although this works, there has got to be a better way of handling this?

Any suggestion would be appreciated.

What I have tried:

I tried looking on the internet for similar setups but was unable to find any matching my situation.
Posted
Updated 12-Mar-17 23:31pm

Yeah, don't use Entity Framework. The problem with using it is that your DbContext is directly tied to the exact version of the database the context was written against. If the database schema changes, the DbContext has to change with it. This prevents you from using the same DbContext against multiple databases even though they have a table structurally in common.

Either you have to switch to using the Sql classes in .NET against each separate database or each of your other site applications is going to have to be redone to all direct their error information to a single database dedicated to error collection, upon which you CAN use Entity Framework.
 
Share this answer
 
Comments
Richard Deeming 9-Mar-17 12:09pm    
Not sure I'd agree with that.

EF only cares about the tables and columns defined in the model. You can have other objects in the database that EF doesn't know or care about. You can even have other columns in the EF tables that EF doesn't know or care about.

The only problem you'd have is if you're inserting a record through EF, and one of the unknown columns is required and doesn't have a default value.

You might want to turn off migrations if you're not using EF to define the database. That way, you won't get the __MigrationHistory table.

But in general, so long as all of the tables and columns for the entities in your EF model exist, and have compatible data types, it should just work.
If all the DbContext classes share the same entities, why not just create a single DbContext class, and use the constructor which takes the name of a connection string to create instances pointing to different databases?
C#
public sealed class ErrorsContext : DbContext
{
    public ErrorsContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
    }
    
    public ISet<Error> Errors 
    {
        get { return Set<Error>(); }
    }
}

public sealed class ErrorsContextConfiguration : DbConfiguration
{
    public ErrorsContextConfiguration()
    {
        // Don't attempt to create / update the database:
        SetDatabaseInitializer(new NullDatabaseInitializer<ErrorsContext>());
    }
}

You can then use a single method to query any one server:
C#
public static IEnumerable<Error> SingleServerQuery(this ErrorsContext context)
{
    return context.Errors. ... ;
}

and then call that against each context instance and combine the results:
C#
public static IEnumerable<Error> MultiServerQuery(params ErrorsContext[] servers)
{
    return servers.SelectMany(context => SingleServerQuery(context));
}
 
Share this answer
 
Comments
Steve Van Lint 9-Mar-17 13:27pm    
This would indeed eliminate the need to create a new DbContext for each database server but I would still need to perform the same query x times for each database server.

I would still need to be able to perform updates on the database.

Currently I am trying an approach with linked servers where I create on db1 the linked servers for db2 and db3 and then perform a union query with raw SQL.

Thanks for the suggestion though
Steve Van Lint 13-Mar-17 5:34am    
I will use this conditional approach to creating the DbContext after all in combination with linked servers, see my latest answer.

Thx for the tip
I have found a way to get this to work.

The different db's are in the same domain and I have the necessary rights on all of them.

What I will do is create linked servers as database objects.

My main db will we db1 and I will use this to populate the tables with the errors.

From db1 I will create linked servers to db2 and 3 (for write purposes).

Db2 and 3 will have a linked server to db1 and will both have a copy of the capture database but without the tables, only the stored procedures.

These SP will write their info directly to db1 and there I will store the point of origin of the error (db1, db2 or db3).

This way I need only query 1 data store to get all relevant info.

In order to update an environment I will need to first determine the instance (a column will hold that info) and conditionally on that info do an update.

For this I will probably go with Richards suggestion and create a new DbContext instance and pass in the connection parameter.
 
Share this answer
 
Comments
TMelton 9895411 29-Jan-24 13:08pm    
I think things have changed since this solution was posted.

Yes this still works for now, but with the ever increasing network security, how long will it be until Cross DB query through linked servers is not allowed. Currently I have a decently complicated setup for my IIS App Pool user to allow for the Second SQL Hop using Kerberos authentication. with group authentications and SPN setup.

I am currently using a linked server, but I'm still searching for the solution or better alternative to this problem.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900