I have several project in a solution. There is a dbContext in the Infrastructure project and I want to migrate, but I get an error. Please tell me what I'm doing wrong and how can I fix it.
using Infrastructure.Models;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<EventModel> Event { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(GetConnectionString());
}
private static string GetConnectionString()
{
const string databaseName = "myDb";
const string databaseUser = "postgres";
const string databasePass = "root";
return $"Server=localhost;" +
$"database={databaseName};" +
$"uid={databaseUser};" +
$"pwd={databasePass};" +
$"pooling=true;";
}
}
}
You have to add constructor without parameters to class ApplicationDbContext.
It is clearly described in link on error image: https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli#using-a-constructor-with-no-parameters
Related
This is Razor form code
#inherits OwningComponentBase<SignatureColoursServices>
List Displaydata=new List();
protected override void OnInitialized()
{
Displaydata = Service.GetSignatures();
}
This is the code in Startup.cs:
services.AddSingleton<ISignatureColoursServices,SignatureColoursServices>();
This is SignatureColour.cs
public string Value { get; set; } = null!;
public string Description { get; set; } = null!;
This is signaturecolourservices.cs:
protected readonly MyDbContext _dbcontext;
public SignatureColoursServices(MyDbContext db)
{
_dbcontext = db;
}
public List<SignatureColour> GetSignatures()
{
return _dbcontext.SignatureColours.ToList();
}
I have tried adding singleton and transient and scoped in startup.cs
You needed to register the service properly. Register SignatureColourServices in the Program.cs file. Please check the below example.
builder.Services.AddScoped<IEmployeeService, EmployeeService>();
builder.Services.AddScoped<ICustomerService, CustomerService>();
builder.Services.AddScoped<SignatureColourServices>();
I am moving code from .net 4.6.1 to .net 6 API. There is a lot of code using: ConfigurationManager.AppSettings["something"].ToString()
to read App.config
In .net6 we use appsettings.json and read it with dependency injection
for example:
private readonly IOptions<Configs> _configs;
public WeatherForecastController(IOptions<Configs> configs)
{
_configs = configs;
}
public IEnumerable<WeatherForecast> Get()
{
var valFromConfig = _configs.Value.Val;
}
How can read settings without passing _configs as parameter of the method?
public IEnumerable<WeatherForecast> Get()
{
var ret = MyClass.GetConfigVal();
}
where MyClass in old solution:
public class MyClass
{
public static string GetConfigVal()
{
return ConfigurationManager.AppSettings["something"].ToString(); // How to change this
}
}
in .net 6 ,You could inject IConfigration into your controller:
private readonly IConfiguration _configuration;
public WeatherForecastController(IConfiguration configuration)
{
_configuration = configuration;
}
public IEnumerable<WeatherForecast> Get()
{
var valFromConfig = _configuration.GetSection(".....").Value;
}
For more details,you could check this document:
So I create classes for setting
public static class ApplicationSettings
{
public const string options = "Appsettings";
public static AppSettings AppSettings { get; private set; } = new AppSettings();
}
public class AppSettings
{
public string SomeSetting { get; set; } = string.Empty;
}
Appsetting.json look like
{
"AppSettings": {
"SomeSetting": "some text"
}
}
Add this to program.cs
ConfigurationManager configuration = builder.Configuration;
configuration.GetSection(ApplicationSettings.options).Bind(ApplicationSettings.AppSettings);
So I can use it everywhere
protected static readonly AppSettings AppSettings = ApplicationSettings.AppSettings;
var mySetting = AppSettings.SomeSetting
I'm using MVC 5, Core 3.1
I have 'AddDbContext' added to my service in Startup.cs.
I then have a Class library core 3.1 project which is my ADO Dal layer.
This is added as a service as well in The ConfigureServices of Startup.cs.
I want to inject the Connection String into the DAL application.
I have:
public partial class ContainerContext : DbContext
{
public ContainerContext()
{
}
public ContainerContext(DbContextOptions<ContainerContext> options) : base(options)
{
}
}
In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
var connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<ContainerContext>(options => options.UseSqlServer(connection));
services.AddDAL();
}
In the Dal project:
public static class ServiceCollectionExtensions
{
// Add parameters if required, e.g. for configuration
public static IServiceCollection AddDAL(this IServiceCollection services)
{
// Register all services as required
services.AddScoped<ILeaseBll, LeaseDal>();
return services;
}
}
The Dal class.
public class LeaseDal : ILeaseBll
{
private string conString;
public LeaseDal(???????)
{
// Some validation for the Context maybe (isNull etc?) throw new ArgumentNullException("conString");
//this.connectionString = conString;
}
How would / should it be done?
Thanks
There is a philosophy change with Dot-Net-Core and Dot-Net-Framework....
public class LeaseDal : ILeaseBll
{
private string conString;
This is not best practice in dot-net-CORE.
You do NOT inject your "connection string" in your concrete DataAccessLayer object.
You inject the db-context.
(and the db-context already has been wired to the Ioc...with its correct connection string)
Something like this:
public interface IDepartmentQueryDomainData()
{
Task<int> GetCountAsync(CancellationToken token);
}
..
public class DepartmentQueryEntityFrameworkDomainDataLayer : IDepartmentQueryDomainData
{
public const string ErrorMessageILoggerFactoryIsNull = "ILoggerFactory is null";
public const string ErrorMessageMyCoolDbContextIsNull =
"MyCoolDbContext is null";
private readonly ILogger<DepartmentQueryEntityFrameworkDomainDataLayer> logger;
private readonly MyCoolDbContext entityDbContext;
public DepartmentQueryEntityFrameworkDomainDataLayer(
ILoggerFactory loggerFactory,
MyCoolDbContext context
{
if (null == loggerFactory)
{
throw new ArgumentNullException(ErrorMessageILoggerFactoryIsNull, (Exception)null);
}
this.logger = loggerFactory.CreateLogger<DepartmentQueryEntityFrameworkDomainDataLayer>();
this.entityDbContext = context ?? throw new ArgumentNullException(
ErrorMessageMyCoolDbContextIsNull,
(Exception)null);
}
public async Task<int> GetCountAsync(CancellationToken token)
{
int returnValue = await this.entityDbContext.Departments.AsNoTracking().CountAsync(token);
this.logger.Log(
new LogEntry(
LoggingEventTypeEnum.Trace,
string.Format(
LogMessages.Count,
returnValue)));
return returnValue;
}
}
You can also "see" this here:
https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/
public class MyController
{
private readonly ApplicationDbContext _context;
public MyController(ApplicationDbContext context)
{
_context = context;
}
}
I would never inject the dbContext into a "controller"...(I agree with you that the Dal should be a separate layer)...
but besides that "miscue" on the microsoft example, you do see that you inject the dbContext.
Also see:
https://hovermind.com/aspnet-core/using-dbcontext-with-dependency-injection.html
I am trying to learn xaml and C# used in Xamarin Forms, and now I want to implement SQLite functionality.
I am simply trying to add a value into a SQL table but get the following error:
Unhandled Exception:
SQLite.SQLiteException: near ")": syntax error occurred
My Database connection interface is as follows:
using SQLite;
namespace TestSQLite
{
public interface IDatabaseConnection
{
SQLiteAsyncConnection GetConnection();
}
}
My Android specific Database Connection (iOS is identical) is as follows:
using SQLite;
using System.IO;
using TestSQLite;
using Xamarin.Forms;
[assembly: Dependency(typeof(DatabaseConnection))]
namespace TestSQLite
{
public class DatabaseConnection : IDatabaseConnection
{
public SQLiteAsyncConnection GetConnection()
{
var dbName = "TestDb.db3";
var path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), dbName);
return new SQLiteAsyncConnection(path);
}
}
}
My MainPage (testpage) is as follows:
using SQLite;
using Xamarin.Forms;
namespace TestSQLite
{
public class ControlledDrugs
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Drug { get; set; }
public double Volume { get; set; }
}
public class Users
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
}
public partial class MainPage : ContentPage
{
private SQLiteAsyncConnection _connection;
public MainPage()
{
InitializeComponent();
_connection = DependencyService.Get<IDatabaseConnection>().GetConnection();
}
protected override async void OnAppearing()
{
await _connection.CreateTableAsync<ControlledDrugs>();
await _connection.CreateTableAsync<Users>();
var drugs = await _connection.Table<ControlledDrugs>().ToListAsync();
Drugslistview.ItemsSource = drugs;
var user = await _connection.Table<Users>().ToListAsync();
Userlistview.ItemsSource = user;
base.OnAppearing();
}
async void OnAdd(object sender, System.EventArgs e)
{
var user = UserInput.Text;
//The next step generates the error
await _connection.InsertAsync(user);
}
void OnUpdate(object sender, System.EventArgs e)
{
}
void OnDelete(object sender, System.EventArgs e)
{
}
}
}
As you can see, I have yet to progress to update or delete. Learning by Youtube and Stackoverflow snippets is painfully slow. But this error got me stumped.
Also, have NuGet package sqlite-net-pcl v1.5.166-beta installed Xamarin Visual Studio.
you are attempting to insert a string into the User table instead of a User object
var user = UserInput.Text;
// user is just a string
await _connection.InsertAsync(user);
instead you need to create a User object
var user = new Users { Name = UserInput.Text };
await _connection.InsertAsync(user);
I have an Asp.Net Core app with Entity Framework Core that I initialize as follows:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(sqlConnectionString));
This works fine, but I have a scenario where I need to read/write from the primary database for normal operations but for some operations I need to read from an alternate server (a replication target that's read only that we use for reporting).
With the way the new Core API does everything via Dependency Injection and configuration in StartUp.cs, how do I switch connection strings, but use the same ApplicationDbContext class?
I know that one option would be to have a duplicate of ApplicationDbContext class that I register with the DI system using a different connection string, but I'd like to avoid maintaining two identical DBContext objects just because sometimes I need to read from a different database server (but with the exact same schema).
Thanks in advance for any pointers!
You'll need two DbContexts.
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class MyBloggingContext : BloggingContext
{
}
public class MyBackupBloggingContext : BloggingContext
{
}
And you can register them like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<MyBackupBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BackupConnection")));
}
Can be done like this(tested with .net core 3.1):
public abstract partial class BloggingContext<T> : DbContext where T : DbContext
{
private readonly string _connectionString;
protected BloggingContext(string connectionString) { _connectionString = connectionString; }
protected BloggingContext(DbContextOptions<T> options) : base(options) { }
public virtual DbSet<Blog> Blogs { get; set; }
public virtual DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
}
}
public class MyBloggingContext : BloggingContext<MyBloggingContext>
{
public MyBloggingContext(string connectionString) : base(connectionString) { }
public MyBloggingContext(DbContextOptions<MyBloggingContext> options) : base(options) { }
}
public class MyBackupBloggingContext : BloggingContext<MyBackupBloggingContext>
{
public MyBackupBloggingContext(string connectionString) : base(connectionString) { }
public MyBackupBloggingContext(DbContextOptions<MyBackupBloggingContext> options) : base(options) { }
}
And in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<MyBackupBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BackupConnection")));
}
Connection string can be resolved using IServiceProvider. In the example below I map query parameter to configuration from appsettings.json, but you could inject any other logic you want.
services.AddDbContext<ApplicationDbContext>((services, optionsBuilder) =>
{
var httpContextAccessor = services.GetService<IHttpContextAccessor>();
var requestParam = httpContextAccessor.HttpContext.Request.Query["database"];
var connStr = Configuration.GetConnectionString(requestParam);
optionsBuilder.UseSqlServer(connStr);
});
?database=Connection1 and ?database=Connection2 in query will lead to using different connection strings. It is worth to provide default value, when parameter is missing.
It can be resolved in this way
public class AppDbContext : DbContext
{
private string _connectionString { get; }
public AppDbContext(string connectionString, DbContextOptions<AppDbContext> options) : base(options)
{
_connectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
Then create the DbContext manually
var appDbContext = new AppDbContext("server=localhost;database=TestDB;Trusted_Connection=true", new DbContextOptions<AppDbContext>());
Instead of hard coding the connection, read from the connection string factory.