EasyDatabaseManager 1.1.1

dotnet add package EasyDatabaseManager --version 1.1.1
                    
NuGet\Install-Package EasyDatabaseManager -Version 1.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EasyDatabaseManager" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EasyDatabaseManager" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="EasyDatabaseManager" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EasyDatabaseManager --version 1.1.1
                    
#r "nuget: EasyDatabaseManager, 1.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EasyDatabaseManager@1.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EasyDatabaseManager&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=EasyDatabaseManager&version=1.1.1
                    
Install as a Cake Tool

Easy Database Manager

NuGet Downloads Target

A lightweight, self-contained SQL data explorer for ASP.NET Core, delivered as a single NuGet package with a simple two-line registration. Browse, search, filter, and edit your database tables through a built-in web UI — without adding Entity Framework Core, without a DbContext, and without any ORM dependency.

Easy Database Manager works with SQL Server, PostgreSQL, MySQL, and SQLite.


Table of contents


Why Easy Database Manager

Most teams eventually need a way to look inside the database from a running ASP.NET Core application — to verify a migration, inspect a support ticket, fix a stuck row, or sanity-check an import. The usual options are heavy: deploy a separate admin tool, expose EF Core scaffolding, or ship a custom CRUD UI.

Easy Database Manager is the small, pragmatic middle ground:

  • Drop it in. Two lines in Program.cs and you have a working table browser at /dev/easy-database-manager.
  • Zero ORM baggage. No DbContext, no migrations, no model-first assumptions. Any existing schema works as-is.
  • Cross-database. One experience across SQL Server, PostgreSQL, MySQL, and SQLite.
  • Safe by default. Hidden columns, masked secrets, read-only key and audit columns, and an explicit toggle for write access.
  • Self-contained. No static files to copy, no CDN, no JavaScript build step.

Intended use cases: internal admin panels, developer and staging tooling, support dashboards, and debugging surfaces inside existing ASP.NET Core apps.


Feature highlights

Core

  • No EF Core, no DbContext, no ORM required.
  • Four database engines supported out of the box: SQL Server, PostgreSQL, MySQL, SQLite.
  • Minimal setup — a single AddEasyDatabaseManager call at registration and a single MapEasyDatabaseManager call to expose the UI.
  • Fully configurable route prefix, page sizes, and column policies.

Data access and safety

  • Hidden columns — never reach the UI.
  • Masked columns — displayed as ••••••••; the value is revealed only on an explicit reveal request and is never included in search.
  • Read-only columns — excluded from updates (primary keys, identity columns, and computed columns are protected automatically; Id is read-only by default, and you can add more via ReadOnlyColumns).
  • Global write toggleEnableWriteOperations disables all edits with a single flag.
  • Soft-delete filteringAll, ActiveOnly, DeletedOnly; works with both boolean-style and nullable-date-style delete markers.

UI

  • Built-in web UI, delivered with the package — nothing to deploy separately.
  • Responsive layout with collapsible sidebar, mobile-friendly design, and light / dark themes.
  • Global search across visible, non-masked columns.
  • Column-level filters with operators: eq, ne, gt, gte, lt, lte, contains, startsWith, endsWith, isnull, notnull.
  • Sortable headers and server-side pagination with configurable page sizes.
  • Inline cell editing with confirm / cancel and server-side validation.
  • Record deletion — a per-row delete button (shown only when writes are enabled) performs a permanent DELETE, gated by EnableWriteOperations and a primary key.
  • Record detail view for a single row across all visible columns.
  • Session-persisted state — the last table, page, filters, and sort survive a reload.
  • Browser history integration — navigating between tables pushes history entries, so the browser Back button returns to the previous table.

UI overview

Once enabled, the UI is available at your configured route prefix (default /dev/easy-database-manager) and surfaces:

  • a sidebar listing every table the connection can see, with live search;
  • a query pane with global search, filter builder, include-deleted toggle, and page-size selector;
  • a results grid with sortable headers and editable cells (when write mode is on);
  • a record detail panel that opens the full row across all visible columns;
  • a theme toggle and mobile-friendly collapsible sidebar.

Requirements

  • .NET 6.0, 7.0, 8.0, 9.0, or 10.0
  • ASP.NET Core (any hosting model: Kestrel, IIS, reverse-proxy, container)
  • A supported database and its ADO.NET provider package (see below)

Installation

dotnet add package EasyDatabaseManager

Or via the Package Manager Console:

Install-Package EasyDatabaseManager

Database providers

Easy Database Manager intentionally does not depend on any specific database provider. Install the provider that matches your database:

Engine Recommended provider
SQL Server Microsoft.Data.SqlClient
PostgreSQL Npgsql
MySQL MySqlConnector (preferred) or MySql.Data
SQLite Microsoft.Data.Sqlite

Example:

dotnet add package Microsoft.Data.SqlClient
# or
dotnet add package Npgsql
# or
dotnet add package MySqlConnector
# or
dotnet add package Microsoft.Data.Sqlite

The provider only needs to be referenced by your host application.


Quick start

using EasyDatabaseManager.Configuration;
using EasyDatabaseManager.Endpoints;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEasyDatabaseManager(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection")!;
    options.DatabaseType     = DatabaseType.SqlServer;

    // UI/route
    options.RoutePrefix           = "/dev/easy-database-manager";
    options.EnableWriteOperations = true;
    options.DefaultPageSize       = 25;
    options.MaxPageSize           = 200;

    // Soft delete
    options.SoftDeleteColumn = "IsValid";

    // Column-level controls
    options.HiddenColumns.Add("PasswordHash");
    options.HiddenColumns.Add("RefreshToken");

    options.MaskedColumns.Add("ApiKey");
    options.MaskedColumns.Add("PrivateKey");
    options.MaskedColumns.Add("SecretKey");

    options.ReadOnlyColumns.Add("TenantId");
});

var app = builder.Build();

// (Optional) protect the explorer behind your own auth.
app.UseAuthentication();
app.UseAuthorization();

app.MapEasyDatabaseManager();

app.Run();

Open the browser at:

https://<your-host>/dev/easy-database-manager

That's it. No scaffolding, no migrations, no static files to copy.


Configuration reference

All options are configured inside the AddEasyDatabaseManager(options => { ... }) delegate.

Option Default Description
ConnectionString required Connection string used to reach your database.
DatabaseType SqlServer One of SqlServer, PostgreSql, MySql, Sqlite.
RoutePrefix /dev/easy-database-manager Route prefix for the UI.
EnableWriteOperations true Master toggle for edits. When false, all update operations are rejected.
DefaultPageSize 25 Default rows per page.
MaxPageSize 200 Hard upper bound on page size.
AccessKey null Optional access key (min 16 chars). Used when Users is empty.
Users empty Dictionary<string,string> of username → password. Enables username/password login. Takes precedence over AccessKey.
SessionSecret null HMAC key for session cookies. If null, a random 32-byte key is generated per process.
AccessSessionDuration 8 hours How long an unlocked session stays valid.
SoftDeleteColumn null Name of the soft-delete column (e.g. DeletedAt, IsActive, IsValid). Enables soft filtering.
HiddenColumns empty Column names to hide completely (case-insensitive).
MaskedColumns empty Column names to display as •••••••• (case-insensitive).
ReadOnlyColumns { "Id" } Additional column names to mark as non-editable.
SchemaCacheDuration 5 minutes How long table and column metadata stay cached between requests.

Default read-only columns

Only Id is treated as read-only out of the box. Add any other columns you want protected — for example audit fields like CreatedAt / UpdatedBy — via options.ReadOnlyColumns.

In addition, primary keys, identity / auto-increment columns, and computed columns are always protected from edits automatically.


Column visibility and editability rules

Every column follows three orthogonal rules:

1. Hidden

Hidden columns are completely removed from the UI — they do not appear in the grid, the record detail, or search results.

options.HiddenColumns.Add("PasswordHash");

2. Masked

Masked columns are shown as ••••••••. The column name remains visible so users know it exists, and the value is revealed only on an explicit reveal request.

options.MaskedColumns.Add("ApiKey");

3. Read-only

Read-only columns are displayed normally but cannot be updated. The following are read-only automatically:

  • every column in options.ReadOnlyColumns
  • primary keys
  • identity / auto-increment columns
  • computed columns
  • hidden columns
options.ReadOnlyColumns.Add("TenantId");

Authentication

The explorer supports three modes, chosen automatically:

Mode Configuration Login UI
Open Neither Users nor AccessKey set No login screen.
Access key AccessKey set, Users empty Single password field.
Users Users has one or more entries Username + password form.

Users takes precedence if both are configured.

Username + password

options.Users["alice"] = "change-me-plz";                 // plaintext, hashed at startup
options.Users["bob"]   = "pbkdf2:100000:<salt>:<hash>";   // pre-hashed, used as-is
options.AccessSessionDuration = TimeSpan.FromHours(4);
options.SessionSecret = "a-long-random-string-for-cookies"; // optional, otherwise random per process

Passwords are hashed with PBKDF2-HMAC-SHA256 (100,000 iterations, per-user random salt) at startup. The plaintext entries in Users are replaced with their hashed form after Validate() runs, so nothing is stored in plain memory afterward. You can supply already-hashed values (prefix pbkdf2:…) if you prefer to keep plaintext out of your config entirely.

Login issues an HttpOnly, SameSite=Strict cookie (Secure on HTTPS) signed with an HMAC over the subject using SessionSecret. Rotate SessionSecret (or change any password) to invalidate all existing sessions.

Access key (single-admin fallback)

options.AccessKey = "change-me-to-a-long-random-string";

A single shared secret, minimum 16 characters. Shown as a password field on the lock screen.

Security notes

  • Treat whatever holds your Users / AccessKey like a secret (appsettings.json, environment variables, a secret manager).
  • The explorer does not rate-limit or lock out failed logins — put it behind a reverse proxy with rate limits if it's exposed to the internet.
  • Mask-reveal and cell edits are allowed for any authenticated user; there are no per-user permissions.

Soft-delete support

Set options.SoftDeleteColumn to enable soft-delete filtering in the UI.

options.SoftDeleteColumn = "DeletedAt";   // or "IsActive", "IsValid", etc.

The explorer supports three modes:

Mode Meaning
All Return all rows regardless of delete flag.
ActiveOnly Return only non-deleted rows. (default)
DeletedOnly Return only deleted rows.

Both boolean-style markers and nullable date markers are supported:

  • Boolean columns (IsActive, IsValid, etc.) follow the convention true = active, false/NULL = deleted.
  • Nullable date columns (DeletedAt, etc.) follow the convention NULL = active, non-null = deleted.

Tables that do not expose the configured soft-delete column are treated as hard-delete tables automatically.


The search box performs a case-insensitive contains-match across all visible, non-masked columns (each is cast to text for matching). Masked and hidden columns are never searched.

Column filters

From the filter builder, add one or more rules using the following operators:

Operator Behavior
eq Equals (or IS NULL when no value is provided).
ne Not equal.
gt, gte Greater than / greater-or-equal.
lt, lte Less than / less-or-equal.
contains Text contains.
startsWith Text starts with.
endsWith Text ends with.
isnull Column value is null.
notnull Column value is not null.

Sorting

Click any visible column header to sort. Click again to reverse the direction.

Pagination

Page size is selectable from the UI and clamped to the configured MaxPageSize.


UI features

  • Table sidebar with live search and responsive collapsing.
  • Global search box across visible text columns.
  • Filter builder — add multiple column filters with typed operators.
  • Sortable headers for every visible column.
  • Include-deleted toggle (visible only when SoftDeleteColumn is configured).
  • Page-size selector with configurable upper bound.
  • Inline cell editing with confirm / cancel and server-side validation.
  • Per-row delete button with a confirm prompt — performs a permanent DELETE; visible only when EnableWriteOperations is on and the table has a primary key.
  • Record detail panel with a one-click open-from-row action.
  • Session-persisted state — the current table, sort, filters, and page survive a page reload.
  • Browser history integration — each table selection pushes a history entry, so the browser Back button navigates to the previous table; Forward restores the next one.
  • Light and dark themes with persistent preference.

Security guidance

Easy Database Manager exposes a powerful surface over your database. Do not expose it to the public internet without authentication. Recommended practices:

  1. Gate the route behind auth. MapEasyDatabaseManager works with the standard ASP.NET Core auth pipeline — add your own [Authorize] policy via endpoint conventions, a minimal-API filter, or a middleware in front of the route prefix.
  2. Use a dedicated connection string scoped to the permissions this tool actually needs.
  3. Disable writes in production unless you have a specific reason otherwise:
    options.EnableWriteOperations = app.Environment.IsDevelopment();
    
  4. Hide secrets. Add columns like PasswordHash, RefreshToken, PrivateKey, or anything PII-sensitive to HiddenColumns.
  5. Mask what must remain visible. Use MaskedColumns for things like ApiKey where the existence matters but the value must not leak.
  6. Put it under a non-obvious route in production, e.g. /internal/_admin/db-<random>.
  7. Put it behind your VPN / private network when possible.

Example — bind the explorer behind an authorization policy:

app.MapGroup("")
   .RequireAuthorization("DbExplorerAccess")
   .MapEasyDatabaseManager();

Advanced scenarios

Multiple environments, single config

builder.Services.AddEasyDatabaseManager(options =>
{
    options.ConnectionString      = builder.Configuration.GetConnectionString("DefaultConnection")!;
    options.DatabaseType          = DatabaseType.PostgreSql;
    options.EnableWriteOperations = !builder.Environment.IsProduction();
    options.RoutePrefix           = builder.Environment.IsProduction()
        ? "/internal/ops/db"
        : "/dev/easy-database-manager";
});

SQLite for a self-contained diagnostics page

builder.Services.AddEasyDatabaseManager(options =>
{
    options.ConnectionString = $"Data Source={Path.Combine(app.Environment.ContentRootPath, "diagnostics.db")}";
    options.DatabaseType     = DatabaseType.Sqlite;
    options.RoutePrefix      = "/diagnostics/db";
});

Tuning metadata caching

For very dynamic schemas, lower SchemaCacheDuration; for stable production schemas, raise it:

options.SchemaCacheDuration = TimeSpan.FromMinutes(30);

Troubleshooting

The application fails to start with a connection-string error. ConnectionString was not set in the AddEasyDatabaseManager delegate. Set it before the app starts.

Tables list is empty. The database user used by the connection string does not have permission to read the schema catalog. Grant the equivalent of VIEW DEFINITION / metadata-read on the target schema.

Updates are rejected with 400. Check, in order:

  1. EnableWriteOperations is true.
  2. The table has a primary key.
  3. The target column is not hidden, read-only, identity, computed, or a primary key.

The UI loads but requests are denied. The route is behind an auth policy you haven't satisfied. Authenticate, or relax the policy for the relevant environment.

Cannot connect to the database. Confirm the matching ADO.NET provider package is installed in the host application, the connection string is valid, and the database is reachable from the host.


FAQ

Does it need Entity Framework Core? No. Easy Database Manager does not require — or interact with — any EF Core DbContext.

Does it generate migrations or scaffolding? No. It reads your existing schema; it does not create, alter, or drop tables.

Can I use it against a read replica? Yes. Point the connection string at the replica and set EnableWriteOperations = false.

How does it handle large tables? Results are paged server-side. MaxPageSize caps how many rows a single page can contain.

Can I restrict which tables are visible? Visibility is controlled by your database user's permissions. Grant SELECT only on the tables you want visible, and use HiddenColumns / MaskedColumns for fine-grained column control.

How do I stop users from editing a specific column? Add the column to ReadOnlyColumns, or mark it as Hidden or Masked depending on whether it should be visible at all.

Can I change the URL where the UI is served? Yes — set options.RoutePrefix to any path you want.

Does the UI require any external resources (CDN, fonts, etc.)? No. The UI is delivered by the package and loads without external dependencies.


Contact support

For support, bug reports, feature requests, or setup questions related to Easy Database Manager, please contact:

✉️ Email: ahmadalkasem371@gmail.com

When reporting an issue, please include:

  • Package version
  • .NET version
  • Database provider used
  • Error message or logs
  • Steps to reproduce the issue

This helps resolve problems faster.


Author

Ahmad Alkasem Software Engineer · .NET Expert ✉️ ahmadalkasem371@gmail.com

Easy Database Manager is designed, developed, and maintained by Ahmad Alkasem. For commercial inquiries, licensing questions, support, or custom integrations, please reach out via email.


License

Easy Database Manager is released under the MIT License. © Ahmad Alkasem. You are free to use, copy, modify, and distribute this package, in whole or in part, subject to the terms of the MIT License.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.