Error:
Cannot create a DbSet for 'OpenIddictEntityFrameworkCoreApplication' because this type is not included in the model for the context.
I found this solution.
However, this solution does not work for .NET 5.0?
Missing reference to OpenIddictApplication" , OpenIddictAuthorization , OpenIddictScope, OpenIddictToken?
OpenIddict.AspNetCore" Version="3.0.0-beta6.20527.75
OpenIddict.EntityFrameworkCore" Version="3.0.0-beta6.20527.75
public class ApiHubContext : DbContext
{
public ApiHubContext(DbContextOptions options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.UseOpenIddict<ApplicationClient, ApplicationAuthorization, ApplicationScope, ApplicationToken, long>();
}
}
public class ApplicationClient : OpenIddictApplication<long, ApplicationAuthorization, ApplicationToken>
{
public bool IsActive { get; set; }
public string Remarks { get; set; }
}
public class ApplicationAuthorization : OpenIddictAuthorization<long, ApplicationClient, ApplicationToken> { }
public class ApplicationScope : OpenIddictScope<long> { }
public class ApplicationToken : OpenIddictToken<long, ApplicationClient, ApplicationAuthorization> { }
These entities have been renamed in 3.0. You can find the complete list here: https://github.com/openiddict/openiddict-core/tree/dev/src/OpenIddict.EntityFrameworkCore.Models
Related
I have inherited a project that has a ton of duplicate Repositories and duplicate Units of Work objects. For instance:
namespace MyProject.Domain.Plant.Repositories
{
public interface IPlantEmployeeRepository : IRepository<Employee>
{
}
}
namespace MyProject.Domain.Plant.UnitOfWorks
{
public interface IPlantUnitOfWork : Common.IUnitOfWork
{
public IPlantEmployeeRepository EmployeeRepository { get; }
public IPlantEmployeeFacilityRepository EmployeeFacilityRepository { get; }
// ...
}
}
namespace MyProject.Infrastructure.Persistence.Plant.Repositories
{
public class PlantEmployeeRepository : Repository<Employee>, IPlantEmployeeRepository
{
public PlantEmployeeRepository(PlantContext context) : base(context)
{
}
}
}
namespace MyProject.Infrastructure.Persistence.Plant.UnitOfWorks
{
public class PlantUnitOfWork : UnitOfWork, IPlantUnitOfWork
{
public IPlantEmployeeRepository EmployeeRepository => ServiceProvider.GetService<IPlantEmployeeRepository>();
public IPlantEmployeeFacilityRepository EmployeeFacilityRepository => ServiceProvider.GetService<IPlantEmployeeFacilityRepository>();
// ...
public PlantUnitOfWork(PlantContext context, IServiceProvider serviceProvider) : base (context, serviceProvider) { }
}
}
// ----------------------------------------------------------------------------------------------
namespace MyProject.Domain.Garage.Repositories
{
public interface IGarageEmployeeRepository : IRepository<Employee>
{
}
}
namespace MyProject.Domain.Garage.UnitOfWorks
{
public interface IGarageUnitOfWork : Common.IUnitOfWork
{
public IGarageEmployeeRepository EmployeeRepository { get; }
public IGarageEmployeeFacilityRepository EmployeeFacilityRepository { get; }
// ...
}
}
namespace MyProject.Infrastructure.Persistence.Garage.Repositories
{
public class GarageEmployeeRepository : Repository<Employee>, IGarageEmployeeRepository
{
public GarageEmployeeRepository(GarageContext context) : base(context)
{
}
}
}
namespace MyProject.Infrastructure.Persistence.Garage.UnitOfWorks
{
public class GarageUnitOfWork : UnitOfWork, IGarageUnitOfWork
{
public IGarageEmployeeRepository EmployeeRepository => ServiceProvider.GetService<IGarageEmployeeRepository>();
public IGarageEmployeeFacilityRepository EmployeeFacilityRepository => ServiceProvider.GetService<IGarageEmployeeFacilityRepository>();
// ...
public GarageUnitOfWork(GarageContext context, IServiceProvider serviceProvider) : base (context, serviceProvider) { }
}
}
Yes - there is no conceptual difference between these 2 representations of the DB. Both address the Employee, EmployeeFacility and other Employee related DB tables. There is no contexual boundaries, no root aggregates, no values and nothing else DDD related except the UoWs and Repositories.
Now, my plan was to create proxy objects that wrapped the UoW/Repositories. II am trying to write a single set of code that does the exact same thing on any collection of Employees, be it the Plant or the Garage or Corporate, etc.
namespace MyProject.Application.Engine.Zone.Proxies
{
public abstract class BaseProxy : IZoneProxyUnitOfWork
{
public IUnitOfWork UnitOfWork { get; internal set; }
public IRepository<IEmployee> RepositoryEmployee { get; internal set; }
public IRepository<IEmployeeFacility> RepositoryEmployeeFacility { get; internal set; }
// ...
}
public class PlantUnitOfWorkProxy : BaseProxy
{
public PlantUnitOfWorkProxy(IPlantUnitOfWork plantUnitOfWork)
{
UnitOfWork = plantUnitOfWork;
RepositoryEmployee = (IRepository<IEmployee>)plantUnitOfWork.EmployeeRepository;
RepositoryEmployeeFacility = (IRepository<IEmployeeFacility>)plantUnitOfWork.EmployeeFacilityRepository;
// ...
}
}
public class GarageUnitOfWorkProxy : BaseProxy
{
public GarageUnitOfWorkProxy(IGarageUnitOfWork garageUnitOfWork)
{
UnitOfWork = garageUnitOfWork;
RepositoryEmployee = (IRepository<IEmployee>)garageUnitOfWork.EmployeeRepository;
RepositoryEmployeeFacility = (IRepository<IEmployeeFacility>)garageUnitOfWork.EmployeeFacilityRepository;
// ...
}
}
}
However, while all of this actually compiles the proxies will not initialize. Conversion from IPlantEmployeeRepository EmployeeRepository to IRepository<IEmployee> RepositoryEmployee is failing (which makes sense). However, my brain is broken enough now that fixing this is putting me in a tailspin: mainly trying to keep track of all the interfaces and how they are being used.
I will say this is a .NET Core solution utilizing C# though I don't think language is the really important here. Just humbly asking for some help.
I want to accomplish clean architecture with EF Core.
I trid to separate primary key from base class, but it failed with below exception.
System.InvalidOperationException: 'A key cannot be configured on 'ManagerEntity' because it is a derived type. The key must be configured on the root type 'Manager'. If you did not intend for 'Manager' to be included in the model, ensure that it is not referenced by a DbSet property on your context, referenced in a configuration call to ModelBuilder, or referenced from a navigation on a type that is included in the model.'
Core
public class Manager
{
public Manager(Guid identifier, string email)
{
Identifier = identifier;
Email = email;
}
public Guid Identifier { get; }
public string Email { get; }
public void FixPrinter(Printer printer)
{
printer.IsOutOfControl = true;
}
}
public class Printer
{
public Printer(Guid token)
{
Token = token;
Manager = null;
IsOutOfControl = false;
}
public Guid Token { get; }
public Manager? Manager { get; set; }
public bool IsOutOfControl { get; set; }
}
Infrastructure
public class ApplicationContext
: DbContext
{
// ...
public DbSet<ManagerEntity> ManagerSet { get; set; }
public DbSet<PrinterEntity> PrinterSet { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new ManagerEntityConfiguration(Database));
modelBuilder.ApplyConfiguration(new PrinterEntityConfiguration(Database));
}
}
Configure Manager
public sealed class ManagerEntity
: Manager
{
public ManagerEntity(string email)
: base(Guid.Empty, email)
{
}
// Primary key for database.
public long Id { get; }
}
internal sealed class ManagerEntityConfiguration
: IEntityTypeConfiguration<ManagerEntity>
{
private readonly DatabaseFacade _database;
public ManagerEntityConfiguration(DatabaseFacade database)
{
_database = database;
}
public void Configure(EntityTypeBuilder<ManagerEntity> builder)
{
builder
.Property(e => e.Id)
.ValueGeneratedOnAdd();
// The exception occurs here.
builder
.HasKey(e => e.Id);
// ...
}
}
Configure Printer
public sealed class PrinterEntity
: Printer
{
public PrinterEntity()
: base(Guid.Empty)
{
}
// Primary key for database.
public long Id { get; }
}
internal sealed class PrinterEntityConfiguration
: IEntityTypeConfiguration<PrinterEntity>
{
private readonly DatabaseFacade _database;
public PrinterEntityConfiguration(DatabaseFacade database)
{
_database = database;
}
public void Configure(EntityTypeBuilder<PrinterEntity> builder)
{
builder
.Property(e => e.Id)
.ValueGeneratedOnAdd();
builder
.HasKey(e => e.Id);
// ...
}
}
Web API
app.MapPost("/printer", async (ApplicationContext context) =>
{
PrinterEntity printer = new()
{
Manager = new ManagerEntity("master#google.com"),
};
await context.PrinterSet.AddAsync(printer);
await context.SaveChangesAsync();
return printer;
});
Should I architect it by using interface, not inheritance?
At Core,
public interface IPrinter
{
public Manager? Manager { get; set; }
}
At Infrastructure,
public sealed class PrinterEntity : IPrinter
{
// ...
}
Github source code
Thanks, #roji!
https://github.com/dotnet/efcore/issues/27421#issuecomment-1034762908
This is likely happening because you're mapping both Manager and ManagerEntity in your model, which means you're configuring inheritance mapping (i.e. EF thinks you intend to store both Manager and ManagerEntity instances in the database). With inheritance mapping, the key must be specified at the root.
However, it seems like you only want the class separation on the .NET side, without needing any actual hierarchy, so make sure you are not mapping the base class (Manager in the above). See the minimal code sample below.
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
public class BlogContext : DbContext
{
// Uncomment the below to make the exception appear
// public DbSet<Manager> Managers { get; set; }
public DbSet<ManagerEntity> ManagerEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(#"Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ManagerEntity>().HasKey(b => b.Id);
}
}
public class Manager
{
public string Name { get; set; }
}
public class ManagerEntity : Manager
{
public int Id { get; set; }
}
However... if the goal is simply not to expose an Id property on Manager, there are simpler ways to do that rather than introducing a .NET hierarchy. You can have a private _id field instead, which would be used by EF Core but not otherwise exposed in your application, keeping your data model clean (see docs). Alternatively, you can have an Id shadow property, removing the field/property from your CLR type altogether.
Summary
I am trying to use Table Per Hierarchy inheritance in conjunction with a one to many relationship in a .Net Core 1.1 project. Both the Parent and child entities use inheritance.
I have a very simple entity model. I have a one base parent entity: Session which has two entities which extend from it: QuotingSession and BackOfficeSession. Both of these two parent entities contain a collection of child entities (a one to many relationship). The child entities are also built using inheritance. There is a base child entity: Policy. This base child entity is extended by two entities: QuotingPolicy and BackOfficePolicy. When I construct either of the Parent entities and attempt to save I receive this exception:
InvalidCastException: Unable to cast object of type 'EFTest.QuotingSession' to type 'EFTest.BackOfficeSession
However, when I tell entity framework to ignore one of the the child collections on either of the parents, the save works for both parent entities with no exception. For example:
var entity = modelBuilder.Entity<BackOfficeSession>();
entity.Ignore(c => c.Policies);
In addition if I do not configure one of the Parents (QuotingSession) at all, and just save the other Parent (BackOfficeSession), everything saves as excepted.
Repo
https://github.com/seantarogers/EFTest
Details
I am using Microsoft.EntityFrameworkCore 1.1.1 and Microsoft.EntityFrameworkCore.SqlServer 1.1.1 in a .Net core 1.1 project.
I have the following simple database schema:
My classes look like this:
1. Session
namespace EFTest
{
public abstract class Session
{
public int Id { get; private set; }
}
}
2. QuotingSession
using System.Collections.Generic;
namespace EFTest
{
public class QuotingSession : Session
{
public string QuotingName { get; private set; }
public List<QuotingPolicy> Policies { get; private set; }
private QuotingSession()
{
}
public QuotingSession(string name, List<QuotingPolicy> quotingPolicies)
{
QuotingName = name;
Policies = quotingPolicies;
}
}
}
3. BackOfficeSession
using System.Collections.Generic;
namespace EFTest
{
public class BackOfficeSession : Session
{
public List<BackOfficePolicy> Policies { get; private set; }
public string BackOfficeName { get; private set; }
private BackOfficeSession()
{
}
public BackOfficeSession(string name, List<BackOfficePolicy> policies)
{
BackOfficeName = name;
Policies = policies;
}
}
}
4. Policy
namespace EFTest
{
public abstract class Policy
{
public int Id { get; set; }
public int SessionId { get; set; }
}
}
5. QuotingPolicy
namespace EFTest
{
public class QuotingPolicy : Policy
{
public string QuotingPolicyName { get; private set; }
private QuotingPolicy()
{
}
public QuotingPolicy(string name)
{
QuotingPolicyName = name;
}
}
}
6. BackOfficePolicy
namespace EFTest
{
public class BackOfficePolicy : Policy
{
public string BackOfficePolicyName { get; private set; }
private BackOfficePolicy()
{
}
public BackOfficePolicy(string name)
{
BackOfficePolicyName = name;
}
}
}
7. EF DB Context and Fluent Configuration
using Microsoft.EntityFrameworkCore;
namespace EFTest
{
public class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions options)
: base(options)
{
}
public DbSet<QuotingSession> QuotingSessions { get; set; }
public DbSet<BackOfficeSession> BackOfficeSessions { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ConfigureSession(modelBuilder);
ConfigurePolicy(modelBuilder);
ConfigureQuotingSession(modelBuilder);
ConfigureBackOfficeSession(modelBuilder);
ConfigureBackOfficePolicy(modelBuilder);
ConfigureQuotingPolicy(modelBuilder);
}
public static void ConfigurePolicy(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<Policy>();
entity.ToTable("Policy", "dbo");
entity.HasKey(x => x.Id);
entity.HasDiscriminator<int>("SessionType")
.HasValue<QuotingPolicy>(1)
.HasValue<BackOfficePolicy>(2);
}
public static void ConfigureBackOfficePolicy(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<BackOfficePolicy>();
entity.Property(x => x.BackOfficePolicyName);
}
public static void ConfigureQuotingPolicy(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<QuotingPolicy>();
entity.Property(x => x.QuotingPolicyName);
}
public static void ConfigureSession(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<Session>();
entity.ToTable("Session", "dbo");
entity.HasKey(x => x.Id);
entity.HasDiscriminator<int>("SessionType")
.HasValue<QuotingSession>(1)
.HasValue<BackOfficeSession>(2);
}
public static void ConfigureBackOfficeSession(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<BackOfficeSession>();
entity.Property(x => x.BackOfficeName);
entity.HasMany(c => c.Policies).WithOne().HasForeignKey(c => c.SessionId);
// entity.Ignore(c => c.Policies); uncomment this to see it working
}
public static void ConfigureQuotingSession(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<QuotingSession>();
entity.Property(x => x.QuotingName);
entity.HasMany(c => c.Policies).WithOne().HasForeignKey(c => c.SessionId);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
}
}
8. To test it
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace EFTest
{
class Program
{
static void Main(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<TestDbContext>();
const string conn = "Server=.\\SqlServer2014;Database=EFTest;Trusted_Connection=True"
optionsBuilder.UseSqlServer(conn);
using (var dbContext = new TestDbContext(optionsBuilder.Options))
{
var quotingPolicy = new QuotingPolicy("quotingPolicyname");
var quotingSession = new QuotingSession("quotingSessionName", new List<QuotingPolicy> {quotingPolicy});
dbContext.QuotingSessions.Add(quotingSession);
dbContext.SaveChanges(); // BLOWS UP HERE!
}
}
}
}
Thanks for your help
In EF Core 2.0, we have the ability to derive from IEntityTypeConfiguration for cleaner Fluent API mappings (source).
How can I extend this pattern to utilize a base entity? In the example below, how can I have a BaseEntityConfiguration to reduce duplication in LanguageConfiguration and MaintainerConfiguration, modifying properties that are in the BaseEntity only in the BaseEntityConfiguration? What would such a BaseEntityConfiguration look like; and how would it be used, if at all, in OnModelCreating()? See the TODOs in-code near the end of the example.
Example:
public abstract class BaseEntity
{
public long Id { get; set; }
public DateTime CreatedDateUtc { get; set; }
public DateTime? ModifiedDateUtc { get; set; }
}
public class Language : BaseEntity
{
public string Iso6392 { get; set; }
public string LocalName { get; set; }
public string Name { get; set; }
}
public class Maintainer : BaseEntity
{
public string Email { get; set; }
public string Name { get; set; }
}
public class FilterListsDbContext : DbContext
{
public FilterListsDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<Language> Languages { get; set; }
public DbSet<Maintainer> Maintainers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//TODO: Possibly add something like BaseEntityConfiguration?
modelBuilder.ApplyConfiguration(new LanguageConfiguration());
modelBuilder.ApplyConfiguration(new MaintainerConfiguration());
}
}
public class LanguageConfiguration : IEntityTypeConfiguration<Language>
{
public void Configure(EntityTypeBuilder<Language> entityTypeBuilder)
{
//TODO: Move this to something like BaseEntityConfiguration?
entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
}
}
public class MaintainerConfiguration : IEntityTypeConfiguration<Maintainer>
{
public void Configure(EntityTypeBuilder<Maintainer> entityTypeBuilder)
{
//TODO: Move this to something like BaseEntityConfiguration?
entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
}
}
Something like this could work (untested)?
public abstract class BaseEntityTypeConfiguration<TBase> : IEntityTypeConfiguration<TBase>
where TBase : BaseEntity
{
public virtual void Configure(EntityTypeBuilder<TBase> entityTypeBuilder)
{
//Base Configuration
}
}
public class MaintainerConfiguration : BaseEntityTypeConfiguration<Maintainer>
{
public override void Configure(EntityTypeBuilder<Maintainer> entityTypeBuilder)
{
entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
base.Configure(entityTypeBuilder);
}
}
There is another way to solve the problem, and that is to use Template Method Design Pattern. Like this:
public abstract class BaseEntityTypeConfiguration<TBase> : IEntityTypeConfiguration<TBase>
where TBase : BaseEntity
{
public void Configure(EntityTypeBuilder<TBase> entityTypeBuilder)
{
//Base Configuration
ConfigureOtherProperties(builder);
}
public abstract void ConfigureOtherProperties(EntityTypeBuilder<TEntity> builder);
}
public class MaintainerConfiguration : BaseEntityTypeConfiguration<Maintainer>
{
public override void ConfigureOtherProperties(EntityTypeBuilder<Maintainer> entityTypeBuilder)
{
entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
}
}
With this way you don't need to write any single line in child configuration.
Another approach if you dont want to repeat the column Definitions for all of your Models that inherit from the same base Entity like this:
protected override void OnModelCreating(ModelBuilder modelBuilder){
modelBuilder.Entity<Order>()
.Property(b => b.CreatedDateTime)
.HasDefaultValueSql("CURRENT_TIMESTAMP ");
modelBuilder.Entity<Adress>()
.Property(b => b.CreatedDateTime)
.HasDefaultValueSql("CURRENT_TIMESTAMP ");
// …
}
is to find all the Entites that inhert from the base Entity, loop over them and call the generic Method as shown below, in which the redundant Logic is placed:
protected override void OnModelCreating(ModelBuilder modelBuilder){
foreach (Type type in GetEntityTypes(typeof(BaseEntity))){
var method = SetGlobalQueryMethod.MakeGenericMethod(type);
method.Invoke(this, new object[] { modelBuilder });
}
}
static readonly MethodInfo SetGlobalQueryMethod = typeof(/*your*/Context)
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Single(t => t.IsGenericMethod && t.Name == "SetGlobalQuery");
public void SetGlobalQuery<T>(ModelBuilder builder) where T : BaseEntity{
builder.Entity<T>().Property(o => o.CreatedDateTime).HasDefaultValueSql("CURRENT_TIMESTAMP");
// Additional Statements
}
For the "GetEntityTypes" Method you need the Nuget Package „Microsoft.Extensions.DependencyModel“
private static IList<Type> _entityTypeCache;
private static IList<Type> GetEntityTypes(Type type)
{
if (_entityTypeCache != null && _entityTypeCache.First().BaseType == type)
{
return _entityTypeCache.ToList();
}
_entityTypeCache = (from a in GetReferencingAssemblies()
from t in a.DefinedTypes
where t.BaseType == type
select t.AsType()).ToList();
return _entityTypeCache;
}
private static IEnumerable<Assembly> GetReferencingAssemblies()
{
var assemblies = new List<Assembly>();
var dependencies = DependencyContext.Default.RuntimeLibraries;
foreach (var library in dependencies)
{
try
{
var assembly = Assembly.Load(new AssemblyName(library.Name));
assemblies.Add(assembly);
}
catch (FileNotFoundException)
{ }
}
return assemblies;
}
Its a bit hacky in my opinion, but works fine for me!
The source with more details:
https://www.codingame.com/playgrounds/5514/multi-tenant-asp-net-core-4---applying-tenant-rules-to-all-enitites
I'm late to the party, but this is what I did in the OnModelCreating method to achieve similar results.
Basically, I have (4) properties that inherit from a BaseEntity. Two of those are dates why two are strings.
For the dates, I wanted the default to be SQL's GETUTCDATE and the string to be "SystemGenerated." Using a static helper that allows me to retrieve the property name from BaseEntity in a strongly-typed manner, I grab the (4) property names. Then, I iterate over all of the iterate over all of the ModelBuilder entities after my primary mappings are set-up. This allows modelBuilder.Model.GetEntityTypes to return the entities that the modelBuidler is aware of. Then it's a matter of looking at the ClrType.BaseType to see if the type inherits from my BaseEntity and setting the defaults on the PropertyBuilder.
I tested this directly and through EF Migrations which confirmed that the proper SQL was generated.
var createdAtUtc = StaticHelpers.GetPropertyName<BaseEntity>(x => x.CreatedAtUtc);
var lastModifiedAtUtc = StaticHelpers.GetPropertyName<BaseEntity>(x => x.LastModifiedAtUtc);
var createdBy = StaticHelpers.GetPropertyName<BaseEntity>(x => x.CreatedBy);
var lastModifiedBy = StaticHelpers.GetPropertyName<BaseEntity>(x => x.LastModifiedBy);
foreach (var t in modelBuilder.Model.GetEntityTypes())
{
if (t.ClrType.BaseType == typeof(BaseEntity))
{
modelBuilder.Entity(t.ClrType).Property(createdAtUtc).HasDefaultValueSql("GETUTCDATE()");
modelBuilder.Entity(t.ClrType).Property(lastModifiedAtUtc).HasDefaultValueSql("GETUTCDATE()");
modelBuilder.Entity(t.ClrType).Property(createdBy).HasDefaultValueSql("SystemGenerated");
modelBuilder.Entity(t.ClrType).Property(lastModifiedBy).HasDefaultValueSql("SystemGenerated");
}
}
Here is the the static helper for getting property names for a given type..
public static string GetPropertyName<T>(Expression<Func<T, object>> expression)
{
if (expression.Body is MemberExpression)
{
return ((MemberExpression)expression.Body).Member.Name;
}
else
{
var op = ((UnaryExpression)expression.Body).Operand;
return ((MemberExpression)op).Member.Name;
}
}
I'm using ServiceStack 4.0.34.
Container.RegisterAutoWire() method works, but when I create an instance of the registered class, no autowiring happens unless I manually call HostContext.Container.AutoWire(this) in the class constructor.
I've read the documentation on GitHub and several entries on stackoverflow. I've tried different overloads of the Register and RegisterAutoWire methods. I have also tried setting the ReuseScope in different ways. No success. No auto-injection of the DbFactory property.
Can anyone tell me if I've missed a step or done something incorrectly? Code snippet below:
public class RouteAppHost : AppHostBase
{
public override void Configure(Container container)
{
container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(
ConfigurationManager.ConnectionStrings["DB"].ConnectionString,
SqlServerOrmLiteDialectProvider.Instance));
container.RegisterAutoWired<MyRepository>().ReusedWithin(ReuseScope.None);
...
}
}
public class MyRepository : RepositoryBase
{
public MyRepository()
{
//Works if this line is uncommented.
//HostContext.Container.AutoWire(this);
}
public List<MyUnit> All()
{
// Db is null as is DbFactory. This throws an exception.
return Db.Select<MyUnit>();
}
}
// For reference, from Metadata
public abstract class RepositoryBase : IDisposable, IRepository
{
protected RepositoryBase();
public virtual IDbConnection Db { get; }
public virtual IDbConnectionFactory DbFactory { get; set; }
public virtual void Dispose();
}
Addendum (1/20/2015): Here is what a service looks like:
public class BlackList
{
public short Key { get; set; }
[StringLength(15)]
public string Name { get; set; }
public bool Active { get; set; }
}
[Route("/queryBlackList/group/{Key}", "GET")]
[Route("/queryBlackList", "GET")]
public class QueryBlackList : IReturn<List<BlackList>>
{
public int Key { get; set; }
}
public class BlackListContext
{
public static List<BlackList> AllRecords()
{
using (var repo = new BlackListRepository())
{
return repo.All();
}
}
}
public class BlackListService : Service
{
public object Get(QueryBlackList request)
{
return BlackListContext.AllRecords();
}
}