Abp.EntityFrameworkCore interface does not implement IDbSet interface as specified on this page: https://aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration?searchKey=AbpDbContext
I want to access MS EFCore directly instead of using Repository (which runs 15X slower than ASP.NET EF). My project is Angluar/Core.
When 'Abp.EntityFrameworkCore' is included in my project I keep getting the following error at Web.Host.Startup.cs, line 134: System.TypeLoadException HResult=0x80131522 Message=Method 'get_IsTraceEnabled' in type 'Abp.Castle.Logging.Log4Net.Log4NetLogger' from assembly 'Abp.Castle.Log4Net, Version=4.6.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation. Source=Abp.Castle.Log4Net
19 Answer(s)
-
0
use Abp.EntityFrameworkCore package
https://aspnetboilerplate.com/Pages/Documents/Entity-Framework-Core
-
0
Implemented code per the above link.
Error occurs in Startup.cs at "//Configure Log4Net logging" on "AddFacility" method.
System.TypeLoadException HResult=0x80131522 Message=Method 'get_IsTraceEnabled' in type 'Abp.Castle.Logging.Log4Net.Log4NetLogger' from assembly 'Abp.Castle.Log4Net, Version=4.6.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation. Source=Abp.Castle.Log4Net StackTrace: at Abp.Castle.Logging.Log4Net.Log4NetLoggerFactory.Create(String name) at Castle.Facilities.Logging.LoggingFacility.RegisterDefaultILogger(ILoggerFactory factory) at Castle.Facilities.Logging.LoggingFacility.Init() at Castle.MicroKernel.DefaultKernel.AddFacility(IFacility facility) at Castle.Windsor.WindsorContainer.AddFacility[T](Action`1 onCreate) at ngTTM.Web.Startup.Startup.<ConfigureServices>b__4_6(AbpBootstrapperOptions options) in C:\Users\Tim\Documents\__ngTTMv700\aspnet-core\src\ngTTM.Web.Host\Startup\Startup.cs:line 146 at Abp.AbpBootstrapper..ctor(Type startupModule, Action`1 optionsAction) at Abp.AbpBootstrapper.Create[TStartupModule](Action`1 optionsAction) at Abp.AspNetCore.AbpServiceCollectionExtensions.AddAbpBootstrapper[TStartupModule](IServiceCollection services, Action`1 optionsAction) at Abp.AspNetCore.AbpServiceCollectionExtensions.AddAbp[TStartupModule](IServiceCollection services, Action`1 optionsAction) at ngTTM.Web.Startup.Startup.ConfigureServices(IServiceCollection services) in C:\Users\Tim\Documents\__ngTTMv700\aspnet-core\src\ngTTM.Web.Host\Startup\Startup.cs:line 143
Web.Host/Startup/Startup.c
public IServiceProvider ConfigureServices(IServiceCollection services) { //MVC services.AddMvc(options => { options.Filters.Add(new CorsAuthorizationFilterFactory(DefaultCorsPolicyName)); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddSignalR(options => { options.EnableDetailedErrors = true; }); //Configure CORS for angular2 UI services.AddCors(options => { options.AddPolicy(DefaultCorsPolicyName, builder => { //App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma. builder .WithOrigins( // App:CorsOrigins in appsettings.json can contain more than one address separated by comma. _appConfiguration["App:CorsOrigins"] .Split(",", StringSplitOptions.RemoveEmptyEntries) .Select(o => o.RemovePostFix("/")) .ToArray() ) .SetIsOriginAllowedToAllowWildcardSubdomains() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); IdentityRegistrar.Register(services); AuthConfigurer.Configure(services, _appConfiguration); //Identity server if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"])) { IdentityServerRegistrar.Register(services, _appConfiguration); } if (WebConsts.SwaggerUiEnabled) { //Swagger - Enable this line and the related lines in Configure method to enable swagger UI services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new Info { Title = "ngTTM API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); options.UseReferencedDefinitionsForEnums(); options.ParameterFilter<SwaggerEnumParameterFilter>(); options.SchemaFilter<SwaggerEnumSchemaFilter>(); options.OperationFilter<SwaggerOperationIdFilter>(); options.OperationFilter<SwaggerOperationFilter>(); options.CustomDefaultSchemaIdSelector(); //Note: This is just for showing Authorize button on the UI. //Authorize button's behaviour is handled in wwwroot/swagger/ui/index.html options.AddSecurityDefinition("Bearer", new BasicAuthScheme()); }); } //Recaptcha services.AddRecaptcha(new RecaptchaOptions { SiteKey = _appConfiguration["Recaptcha:SiteKey"], SecretKey = _appConfiguration["Recaptcha:SecretKey"] }); if (WebConsts.HangfireDashboardEnabled) { //Hangfire(Enable to use Hangfire instead of default job manager) services.AddHangfire(config => { config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default")); }); } if (WebConsts.GraphQL.Enabled) { services.AddAndConfigureGraphQL(); } // configure NgTtmAbpDbContext context services.AddAbpDbContext<NgTtmAbpDbContext>(options => { options.DbContextOptions.UseSqlServer(options.ConnectionString); }); //Configure Abp and Dependency Injection return services.AddAbp<ngTTMWebHostModule>(options => { //Configure Log4Net logging options.IocManager.IocContainer.AddFacility<LoggingFacility>( f => f.UseAbpLog4Net().WithConfig("log4net.config") ); options.PlugInSources.AddFolder(Path.Combine(_hostingEnvironment.WebRootPath, "Plugins"), SearchOption.AllDirectories); }); }
DbContextLibrary/NgTtmAbpDbContext.cs
using Abp.EntityFrameworkCore; using Abp.Modules; using Microsoft.EntityFrameworkCore; using ngTTM.TtmDataModel; namespace DbContextLibrary { [DependsOn(typeof(AbpEntityFrameworkCoreModule))] public class NgTtmAbpDbContext : AbpDbContext { public virtual DbSet<AnswerMatch> AnswerMatchs { get; set; } public virtual DbSet<Answer> Answers { get; set; } public virtual DbSet<Question> Questions { get; set; } public virtual DbSet<QuestionBank> QuestionBanks { get; set; } public NgTtmAbpDbContext(DbContextOptions<NgTtmAbpDbContext> options) : base(options) { } } }
Web.Host/Startup/ngTTMWebHostModule.cs
public override void PreInitialize() { Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat = _appConfiguration["App:ServerRootAddress"] ?? "http://localhost:22742/"; Configuration.Modules.AspNetZero().LicenseCode = _appConfiguration["AbpZeroLicenseCode"]; Configuration.DefaultNameOrConnectionString = GetConnectionString("Default"); } private string GetConnectionString(string conn) { var appsettingsjson = JObject.Parse(File.ReadAllText("appsettings.json")); var dbConnectionStrings = (JObject)appsettingsjson["ConnectionStrings"]; string connStr = dbConnectionStrings.Property("Default").Value.ToString(); return connStr; }
-
0
Method 'get_IsTraceEnabled' in type 'Abp.Castle.Logging.Log4Net.Log4NetLogger' from assembly 'Abp.Castle.Log4Net, Version=4.6.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
https://github.com/aspnetboilerplate/aspnetboilerplate/issues/4445#issuecomment-495637354 https://github.com/aspnetboilerplate/aspnetboilerplate/pull/4539
Usually you only need to upgrade the ABP package.
-
0
Upgraded Abp.Castle.Log4Net, Abp.RedisCcache, Abp, Abp.ZeroCore from 4.6.0 to 4.8.1. Startup works fine. Using context causes Exception:
Message: LoadQuestionsXml.cs, ParseQuestionFile Exception Type: System.InvalidOperationException Exception: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext. Source: Microsoft.EntityFrameworkCore Stack Trace: at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context) at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_Model() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider() at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) at ImportFilesLibrary.LoadQuestionsXml.ParseQuestionFile(MemoryStream FileContent, Int32 QuestionBankId, Nullable`1 userId) in C:\Users\Tim\Documents\__ngTTMv700\aspnet-core\...myfile.cs
...at " var data = context.QuestionBanks.FirstOrDefault(b => b.Id == 123);"
public class myClass { private static DbContextOptions<NgTtmAbpDbContext> dbContextOptions = new DbContextOptions<NgTtmAbpDbContext>(); public void MyFunction() { using (NgTtmAbpDbContext context = new NgTtmAbpDbContext(dbContextOptions)) { var data = context.QuestionBanks.FirstOrDefault(b => b.Id == 123); }
Tried resolving error message, but Google searched solutions did not work.
-
0
In general you should not use AbpDbContext directly. You should use Repository. https://aspnetboilerplate.com/Pages/Documents/Repositories
I suggest you first check the abp & abp zero documentation.
https://aspnetboilerplate.com/Pages/Documents/ https://docs.aspnetzero.com/documents/common/latest/
-
0
I initially migrated some ASP.NET code to my ANZ app and used injection and IRepository as is used throughout ANZ. However, the performance for db-intensive operations is 15X SLOWER (due I surmise to the transactional nature of the interface). The db-intensive portion of my app is not built on the transaction model. Your first reply in this thread directed me to Enitity-Framework-Core, which I implemented. Now you're telling me that I shouldn't use it. The app I'm migrating from ASP.NET accessed EF directly. ANZ InitialHostDbBuilder class uses EF context directly. I need to access EF directly for performance reasons. Why can't access context directly in my app? Given https://aspnetboilerplate.com/Pages/Documents/Entity-Framework-Core is published documentation, how to I make it work?
-
0
You can try to get DbContext using IDbContextProvider instead of creating it manually.
-
0
Could you please direct me to the documentation and some sample code?
-
0
Very simple, inject the
IDbContextProvider
interface and then call the method to get theDbContext
.public interface IDbContextProvider<out TDbContext> where TDbContext : DbContext { TDbContext GetDbContext(); TDbContext GetDbContext(MultiTenancySides? multiTenancySide ); }
https://github.com/aspnetzero/aspnet-zero-core/blob/16582df85fbceba18fe61fdd613d1093ef25921c/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Application/HealthChecks/AbpZeroTemplateDbContextUsersHealthCheck.cs#L14
-
0
I implemented the changes as described above. My app compiles and runs without encountering Exceptions. The records in the db are as expected. However, the performance of the IDbContextProvider interface is 10X SLOWER than the equivalent MS EntityFramework context db access in ASP.NET, and is transactional. No data is actually written to the db until the thread completes and the IDbContextProvider is Disposed by the task caller. Multiple calls to "context.SaveChanges()" have no effect on the db. Why must I use IDbContextProvider interface? How can I get better performance from this interface? How can I override the transactional nature of this interface (without resorting to more overhead via UnitOfWork)? Why can I not use MS EntityFrameworkCore directly? And if I can, how?
-
0
Because the entire framework is based on dependency injection.
No database provider has been configured for this DbContext. ....
try
var builder = new DbContextOptionsBuilder<AbpZeroTemplateDbContext>(); builder.UseSqlServer(_appConfiguration.GetConnectionString("Default")); var db = new AbpZeroTemplateDbContext(builder.Options); var user = db.Users.FirstOrDefault();
-
0
Getting an Exception when the above is implemented:
Exception Type: System.InvalidOperationException Exception: Unable to determine the relationship represented by navigation property 'User.DeleterUser' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. Source: Microsoft.EntityFrameworkCore Stack Trace: at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyMappingValidationConvention.Apply(InternalModelBuilder modelBuilder) at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuilder) at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel() at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode) --- End of stack trace from previous location where exception was thrown --- at System.Lazy`1.CreateValue() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() at lambda_method(Closure , ServiceProviderEngineScope ) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_Model() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider() at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) at ImportFilesLibrary.LoadQuestionsXml.ParseQuestionFile(MemoryStream FileContent, Int32 QuestionBankId, Nullable`1 userId) in C:\Users\Tim\Documents\__ngTTMv700\aspnet-core\ttm\ImportFilesLibrary\LoadQuestionsXml.cs:line 69
at LoadQuestionsXml.cs:line 69 is fhe following code:
QuestionBank questionBank = context.QuestionBanks .FirstOrDefault(b => b.QuestionBankId == QuestionBankId);
NgTtmAbpDbContext.cs
using Abp.EntityFrameworkCore; using Abp.Modules; using Microsoft.EntityFrameworkCore; using ngTTM.TtmDataModel; namespace DbContextLibrary { [DependsOn(typeof(AbpEntityFrameworkCoreModule))] public class NgTtmAbpDbContext : AbpDbContext { public virtual DbSet<AnswerMatch> AnswerMatchs { get; set; } public virtual DbSet<Answer> Answers { get; set; } public virtual DbSet<Question> Questions { get; set; } public virtual DbSet<QuestionBank> QuestionBanks { get; set; } public NgTtmAbpDbContext(DbContextOptions<NgTtmAbpDbContext> options) : base(options) { } } }
Implemented the code fragment you suggested as:
var builder = new DbContextOptionsBuilder<NgTtmAbpDbContext>(); string connStr = _appConfiguration.GetConnectionString("Default"); builder.UseSqlServer(connStr); NgTtmAbpDbContext context = new NgTtmAbpDbContext(builder.Options);
-
0
hi @timmackey Can you reproduce your problem using Zero's Demo project? Send to: [email protected]
-
0
The previously reported Exception has been eliminated by modifying the class as follows:
public class NgTtmAbpDbContext : AbpZeroDbContext<Tenant, Role, User, NgTtmAbpDbContext>
No Exceptions occur, however, an earlier created table is not being updated:
QuestionBank questionBank = context.QuestionBanks .FirstOrDefault(b => b.QuestionBankId == QuestionBankId); if (questionBank == null) { status.FailureReason = FailureReason("UnableToOpenQuestionBankId_0", QuestionBankId.ToString()); status.Success = false; return status; } questionBank.ItemsTotal = elementCount * 2; questionBank.ItemsProcessed = 0; context.SaveChanges();
"context.SaveChanges();" is not updating QuestionBanks table.
-
0
hi @timmackey
The code you shared made me unable to determine the problem.
Can you reproduce your problem using Zero's Demo project? Send to: [email protected]
-
0
Created a project based on Zero's Demo project.
Unable to reproduce the error
Exception: Unable to determine the relationship represented by navigation property 'User.DeleterUser' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
in the Demo project due, I suspect, to the specific table/foreign key relationships in my db, which I would be impractical to reproduce in a demo project.
I will submit a new issue that I need to resolve that may reveal a solution to this issue.
-
0
Hi @timmackey
Your last problem might be related to https://github.com/aspnetboilerplate/aspnetboilerplate/issues/4691
-
0
Hi @timmackey
Did you have a chance to try this ?
-
0
The above suggested solution was only partially related to my problem. I solved the issue by conditionally compiling out foreign keys (but not the id) in tables that referenced referenced Tenant. i.e.
[Table("Buildings")] public class Building : FullAuditedEntity , IMayHaveTenant { #if !CUSTOM_DB_CONTEXT_LIB [ForeignKey("TenantId")] public virtual Tenant Tenant { get; set; } #endif public virtual int? TenantId { get; set; } [Required] [StringLength(BuildingConsts.MaxBuildingNameLength, MinimumLength = BuildingConsts.MinBuildingNameLength)] public virtual string BuildingName { get; set; } ... }
This allows me to use the same table definition files in ANZ-generated context
public class AnzAppDbContext : AbpZeroDbContext<Tenant, Role, User, AnzAppDbContext>, IAbpPersistedGrantDbContext
and my custom context for .NET Core 2.2, which is...using Microsoft.EntityFrameworkCore; namespace CustomDbContextLibrary { public class CustomDbContext : DbContext { public virtual DbSet<Building> Buildings { get; set; } ... public virtual DbSet<Room> Rooms { get; set; } public ExamDbContext(DbContextOptions<ExamDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } } }
The class constructor is
using Microsoft.EntityFrameworkCore; #if CUSTOM_DB_CONTEXT_LIB using CustomDbContextLibrary; using DbContext = CustomDbContextLibrary.CustomDbContext; #else using AnzApp.AnzAppDataModel; using DbContext = AnzApp.EntityFrameworkCore.AnzAppDbContext; #endif using Abp.EntityFrameworkCore; using Abp.Domain.Uow; using System.Transactions; using Microsoft.Extensions.Configuration; using Microsoft.AspNetCore.Hosting; private readonly IDbContextProvider<DbContext> _dbContextProvider; private readonly IConfigurationRoot _appConfiguration; private readonly DbContextOptionsBuilder<DbContext> _dbContextOptionsBuilder; //----------------------------------------------------------------------------------------- public CreateSomethingClass( IDbContextProvider<DbContext> dbContextProvider, IHostingEnvironment hostingEnvironment ) { _dbContextProvider = dbContextProvider; _appConfiguration = hostingEnvironment.GetAppConfiguration(); _dbContextOptionsBuilder = new DbContextOptionsBuilder<DbContext>(); string connStr = _appConfiguration.GetConnectionString("Default"); _dbContextOptionsBuilder.UseSqlServer(connStr); }
Usage is
public virtual bool Create(string guid, string rootFolder) { using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)) { DbContext context = new DbContext(_dbContextOptionsBuilder.Options); { Building bldg = context.Buildings.First(x => x.BuildingName == "Electric Tower") ; bldg.BuildingName = "Tower Two"; context.SaveChanges(); ... // thousands of lines of code not shown } } }
This provides performance equivalent to ASP.NET EntityFramework when referencing many tables for high frequency bursts of create/read/update rows.
Making the Create method virtual, as suggested in ticket #7635 eliminates transactional nature of db access. This resolves all issues.
@maliming and @ismcagdas - Thank you for your all your suggestions.