So i have set up a migration which seems to work fine, the only issues is that my datetimeoffset becomes a timespan in the database, when i run the migration.
And i cannot seem to figure out why, any help would be usefull.
Google and Umbraco forum or documentation have not been very helpfull.
Here is my complete code.
My Schema
public class ArticleLikeSchema
{
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 1)]
[Column("Id")]
public int Id { get; set; }
[Column("Liked")]
public bool Liked { get; set; }
[Column("UmbracoPageId")]
public int UmbracoPageId { get; set; }
[Column("UserID")]
public string UserID { get; set; }
[Column("Created")]
public DateTimeOffset Created { get; set; }
}
My Migration
public class AddArticleLikesTable : MigrationBase
{
private readonly ILogger logger;
public AddArticleLikesTable(IMigrationContext context, ILogger logger) : base(context)
{
this.logger = logger;
}
public override void Migrate()
{
logger.Debug<AddArticleLikesTable>("Running migration {MigrationStep}", "AddArticleCommentsTable");
// Lots of methods available in the MigrationBase class - discover with this.
if (TableExists("ArticleLikes") == false)
{
Create.Table<ArticleLikeSchema>().Do();
}
else
{
logger.Debug<AddArticleLikesTable>("The database table {DbTable} already exists, skipping", "ArticleComments");
}
}
}
And my Component
public class ArticleLikeMigrationComponent : IComponent
{
private readonly ILogger logger;
private readonly IScopeProvider scopeProvider;
private readonly IMigrationBuilder migrationBuilder;
private readonly IKeyValueService keyValueService;
public ArticleLikeMigrationComponent(ILogger logger, IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService)
{
this.logger = logger;
this.scopeProvider = scopeProvider;
this.migrationBuilder = migrationBuilder;
this.keyValueService = keyValueService;
}
public void Initialize()
{
// Create a migration plan for a specific project/feature
// We can then track that latest migration state/step for this project/feature
var likesMigrationPlan = new MigrationPlan("ArticleLikes");
// This is the steps we need to take
// Each step in the migration adds a unique value
likesMigrationPlan.From(string.Empty)
.To<AddArticleLikesTable>("Article-Like-migration");
// Go and upgrade our site (Will check if it needs to do the work or not)
// Based on the current/latest step
var upgrader2 = new Upgrader(likesMigrationPlan);
upgrader2.Execute(scopeProvider, migrationBuilder, keyValueService, logger);
}
public void Terminate()
{
}
}
What are you trying to do? If you want a date, you could use DateTime instead?
[Column(TypeName="DateTime")]
public DateTime Created { get; set; }
You could also try:
public class AddExtraColumns : MigrationBase
{
public AddExtraColumns(IMigrationContext context) : base(context) {}
public override void Migrate()
{
Create.Column("Created").OnTable("gfdgdf").AsDate(50).Nullable().Do();
}
}
Related
I'm studying design patterns in .NET and currently i'm trying to implement the State Pattern. But today i got to a problem and i can't figure out how to fix this situation.
I have some state classes, all of them implementing the state interface. One of the last states should connect to a data base, through a service injected by the .NET API Startup class, to persist the data and finish up the process.
The problem is... because of the dependency injection that i need to be in the final state, i can't instanciate this state object to progress to this point. I don't know how to continue from there. I don't know if i'm using the pattern wrong or if the use of dependency injection in this pattern is the problem. I can't give all the details of the problem because my studie's project is a little big mess at this moment, so i made a quick mimic of the structure i'm trying to build in my application.
States interface and the OperatingClass who will execute the state behaviour:
public interface IOperationState
{
public int ExecuteOperation(OperatingClass operatingClass);
}
public class OperatingClass
{
public IOperationState OperationState { get; set; }
public int id { get; set; }
public double value { get; set; }
public OperatingClass(int id) //constructor
{
this.id = id;
value = 0;
OperationState = new StartingState();
}
public int Execute()
{
return OperationState.ExecuteOperation(this);
}
}
Main Service: is the service who my controller calls after receive the API Post Method:
public class MainService
{
public int ExecuteFullOperation(int id)
{
//Receives an id and execute the state transition till the end;
var operatingClass = new OperatingClass(id);
return operatingClass.Execute();
}
}
The classes who represents the states and do the respective actions:
public class StartingState : IOperationState
{
public int ExecuteOperation(OperatingClass operatingClass)
{
// Do something...
operatingClass.OperationState = new MiddleState();
return operatingClass.Execute();
}
}
public class MiddleState : IOperationState
{
public int ExecuteOperation(OperatingClass operatingClass)
{
//Do something with the value... let's supose the result is 123, but it does not matter rn;
operatingClass.value = 123;
//Here is the problem: FinalState needs the PersistenceService, who
//receives a injected class to acess the database;
operatingClass.OperationState = new FinalState();
//I want to execute it and return the sucess or failure of the persistence.
return operatingClass.Execute();
}
}
public class FinalState : IOperationState
{
private readonly IPersistenceService PersistenceService;
public FinalState(IPersistenceService persistenceService)
{
PersistenceService = persistenceService;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
return PersistenceService.PersistData(operatingClass.id, operatingClass.value) ? 200 : 503;
}
}
Additional info: i made the PersistenceService be injected in the Startup.cs as a Transient (i dont know how to make it in another way at this moment).
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IPersistenceService, PersistenceService>();
// Irrelevant configurations for the question.
services.AddControllers();
}
Please, help me if you can. I'm having a hard time trying to figure it out by myself.
Thank you for your patience and for your time reading it.
Firstly, we need some simple factory which will supply all necessary dependencies by their type. So let's create types for states:
public enum StateType
{
Start,
Middle,
Final
}
And simple factory:
public class StateFactory
{
private Dictionary<StateType, IOperationState> _stateByType;
// you can inject these dependencies through DI like that:
// public StateFactory(StartingState startingState,
// MiddleState middleState, FinalState finalState,
// PersistenceService persistenceService)
public StateFactory()
{
_stateByType = new Dictionary<StateType, IOperationState>()
{
{ StateType.Start, new StartingState(this) },
{ StateType.Middle, new MiddleState(this) },
{ StateType.Final, new FinalState(new PersistenceService()) }
};
}
public IOperationState GetByType(StateType stateType) =>
_stateByType[stateType];
}
Then we should register all our dependencies:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IPersistenceService, PersistenceService>();
services.AddTransient<StartingState>();
services.AddTransient<MiddleState>();
services.AddTransient<FinalState>();
services.AddTransient<MainService>();
services.AddTransient<OperatingClass>();
services.AddTransient<PersistenceService>();
services.AddTransient<StateFactory>();
}
Our states would look like this:
public class StartingState : IOperationState
{
private StateFactory _factory;
public StartingState(StateFactory stateFactory)
{
_factory = stateFactory;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
// Do something...
// operatingClass.OperationState = new MiddleState();
operatingClass.OperationState = _factory.GetByType(StateType.Middle);
return operatingClass.Execute();
}
}
And MiddleState would look like this:
public class MiddleState : IOperationState
{
private StateFactory _factory;
public MiddleState(StateFactory stateFactory)
{
_factory = stateFactory;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
//Do something with the value... let's supose the result is 123,
// but it does not matter rn;
operatingClass.value = 123;
//Here is the problem: FinalState needs the PersistenceService, who
//receives a injected class to acess the database;
operatingClass.OperationState = _factory.GetByType(StateType.Final);
//I want to execute it and return the sucess or failure of the persistence.
return operatingClass.Execute();
}
}
And Final state should look like this:
public class FinalState : IOperationState
{
private readonly IPersistenceService _persistenceService;
public FinalState(IPersistenceService persistenceService)
{
_persistenceService = persistenceService;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
return _persistenceService
.PersistData(operatingClass.id, operatingClass.value)
? 200
: 503;
}
}
And other classes sush as OperatingClass would use StateFactory too:
public class OperatingClass
{
public IOperationState OperationState { get; set; }
public int id { get; set; }
public double value { get; set; }
public OperatingClass(int id, StateFactory stateFactory) //constructor
{
this.id = id;
value = 0;
// OperationState = new StartingState();
OperationState = stateFactory.GetByType(StateType.Start);
}
public int Execute()
{
return OperationState.ExecuteOperation(this);
}
}
And it is necessary to create concrete example of PersistenceService:
public interface IPersistenceService
{
bool PersistData(int id, double value);
}
public class PersistenceService : IPersistenceService
{
public bool PersistData(int id, double value)
{
throw new NotImplementedException();
}
}
I am implementing a scheduler. As part of its core logic it processes a custom object Schedule. Basically it iterates over an array of schedules and try to process it. The problem is who ever creates a Schedule needs to register it with the container using an ISchedule interface. My Scheduler then pulls all the ISchedule references from the container. SO far this is working but it does not have the flexibility of loading the schedules runtime. What design and implementation I can adapt to implement a Scheduler that can load those Schedules run time. I am giving some sample code.
Something that is coming to my mind is having the developers writing a json representation of the Schedules and put that inside a config or implementing an endpoint that returns that config to the Scheduler. But can I avoid this? I want the Scheduler to be completely agonistic of developer code.
You can use the factory to register information about schedule classes. And dynamically change the call interval by finding the schedule by Id.
You register in the container: <IScheduleFactory,ScheduleFactory> and <IScheduleManager,ScheduleManager>
public interface ISchedule
{
public string Id { get; set; }
public TimeSpan Interval { get; set; }
public DateTime? LastExecution { get; set; }
public bool CanStart { get; }
void Start();
void Stop();
}
public sealed class Schedule : ISchedule
{
public string Id { get; set; }
public TimeSpan Interval { get; set; }
public DateTime? LastExecution { get; set; }
public bool CanStart {
get
{
lock (_sync)
{
return !LastExecution.HasValue || LastExecution.Value.Add(Interval) >= DateTime.UtcNow;
}
}
}
private readonly object _sync = new object();
public void Start()
{
lock (_sync)
{
if (!LastExecution.HasValue || LastExecution.Value.Add(Interval) >= DateTime.UtcNow)
{
// DO WORK
LastExecution = DateTime.UtcNow;
}
}
}
public void Stop()
{
throw new NotImplementedException();
}
}
public interface IScheduleFactory
{
ISchedule Create();
}
public sealed class ScheduleFactory: IScheduleFactory
{
private readonly IScheduleManager _manager;
public ScheduleFactory(IScheduleManager manager)
{
_manager = manager;
}
public ISchedule Create()
{
var schedule = new Schedule();
_manager.Register(schedule);
return schedule;
}
}
public interface IScheduleManager
{
void Register(ISchedule schedule);
ISchedule Get(string id);
void Start();
void Stop();
}
public sealed class ScheduleManager : IScheduleManager
{
private readonly Dictionary<string,ISchedule> _items = new Dictionary<string, ISchedule>();
private readonly object _sync = new object();
public void Register(ISchedule schedule)
{
lock (_sync)
{
if (_items.ContainsKey(schedule.Id))
_items.Add(schedule.Id, schedule);
}
}
public ISchedule Get(string id)
{
lock (_sync)
{
if (_items.ContainsKey(id))
return _items[id];
}
return null;
}
private bool _isStart;
public void Start()
{
_isStart = true;
while (_isStart)
{
ISchedule[] array = null;
lock (_sync)
{
array = _items.Values.ToArray();
}
foreach (var schedule in array)
{
if (schedule.CanStart)
Task.Factory.StartNew(()=>schedule.Start());
}
}
}
public void Stop()
{
_isStart = false;
}
}
How can I change the following action to get a single result by ID?
I have the following code to get All records from the database, I want to modifiy it so that I can get a single record.
namespace PDS.Core.App.Data.Action.Product
{
public class GetProducts_Action : BaseEFAction<GetProducts_Action_Request, GetProducts_Action_Response>
{
private CRMSContext Context { get; }
private IMapper Mapper { get; }
public GetProducts_Action(ILogger<GetProducts_Action> logger, CRMSContext context, ITransactionManager scope, IMapper mapper) : base(logger, context, scope)
{
Context = context.ValidateAndConsumeNonNullableArgument(nameof(context));
Mapper = mapper.ValidateAndConsumeNonNullableArgument(nameof(mapper));
}
protected override async Task<GetProducts_Action_Response> PerformActionAsync(GetProducts_Action_Request request)
{
var tb_Products = await Context.TB_Products
.ToListAsync();
var tb_ProductsDTOs = Mapper.Map<IList<TB_ProductDTO>>(tb_Products);
return new GetProducts_Action_Response { TB_Products = tb_ProductsDTOs };
}
}
public class GetProducts_Action_Request : BaseActionRequest
{
}
public class GetProducts_Action_Response : BaseActionResponse
{
public IList<TB_ProductDTO> TB_Products { get; set; }
}
}
You need to write the code a bit if you extend the code instead of modifying it.
First, you can create a new request class similar to GetProducts_Action_Request that has ProductId in order to use it for getting a single product item. For example, let's say GetProduct_Action_Request:
public class GetProduct_Action_Request : BaseActionRequest
{
public int ProductId {get; set;}
}
And response object that has single product:
public class GetProduct_Action_Response : BaseActionResponse
{
public TB_ProductDTO TB_Product { get; set; }
}
Then you need to create new action GetProduct_Action similar to GetProducts_Action. And you can use SingleOrDefaultAsync to return the only Product element that satisfies a Id condition:
public class GetProduct_Action : BaseEFAction<GetProduct_Action_Request, GetProduct_Action_Response>
{
private CRMSContext Context { get; }
private IMapper Mapper { get; }
public GetProduct_Action(ILogger<GetProduct_Action> logger, CRMSContext context, ITransactionManager scope, IMapper mapper) : base(logger, context, scope)
{
Context = context.ValidateAndConsumeNonNullableArgument(nameof(context));
Mapper = mapper.ValidateAndConsumeNonNullableArgument(nameof(mapper));
}
protected override async Task<GetProduct_Action_Response> PerformActionAsync(GetProduct_Action_Request request)
{
var tb_Product = await Context.TB_Products.SingleOrDefaultAsync(i=> i.Id == request.ProductId);
var tb_ProductDTO = Mapper.Map<IList<TB_ProductDTO>>(tb_Product);
return new GetProduct_Action_Response { TB_Product = tb_ProductDTO };
}
}
public class GetProduct_Action_Request : BaseActionRequest
{
public int ProductId {get; set;}
}
public class GetProduct_Action_Response : BaseActionResponse
{
public TB_ProductDTO TB_Product { get; set; }
}
Therefore you have 2 actions GetProduct_Action for a single product based on Id and GetProducts_Action for a list of all products.
I am receiving null exception error on my framework. I have tried to apply Repository and Unit of Work design patterns in my application. What I am trying to do is simply retreiving user titles from my data base with GetAll() method.
Here is my repository class:
public class Repository<T> : IRepository<T> where T : class
{
protected readonly DbContext Context;
public Repository(DbContext context)
{
this.Context = context;
}
public T Get(int id)
{
return Context.Set<T>().Find(id);
}
public IEnumerable<T> GetAll()
{
return Context.Set<T>().ToList();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Where(predicate);
}
public void Add(T entity)
{
Context.Set<T>().Add(entity);
}
public void AddRange(IEnumerable<T> entityList)
{
Context.Set<T>().AddRange(entityList);
}
public void Remove(T entity)
{
Context.Set<T>().Remove(entity);
}
public void RemoveRange(IEnumerable<T> entityList)
{
Context.Set<T>().RemoveRange(entityList);
}
}
This is IUserTitlesRepository:
public interface IUserTitlesRepository : IRepository<UserTitles>
{
}
And, the class where above interface implemented:
public UserTitlesRepository(XaPaDataContext context) : base(context)
{
}
public XaPaDataContext XaPaDataContext
{
get { return Context as XaPaDataContext; }
}
Before coming to Controller layer, I have two more layers, which are Operation and Manager layers. And, I think I have messed up on that part (on Base Manager class as shown below).
This is operation layer:
public class UserTitlesOperations
{
private readonly IUnitOfWork _uow;
public UserTitlesOperations(IUnitOfWork uow)
{
_uow = uow;
}
public List<UserTitles> GetAllUserTitles()
{
try
{
List<UserTitles> userTitleList = _uow.UserTitles.GetAll().ToList();
_uow.Complete();
return userTitleList;
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
}
Below is the BaseManager class which gives inheritance to all manager classes.
public abstract class BaseManager
{
private IUnitOfWork _iUow;
private readonly XaPaDataContext _context;
public IUnitOfWork IUOW
{
get
{
if (_iUow == null)
{
_iUow = new XaPaUnitOfWork(_context);
}
return _iUow;
}
}
}
This is the manager class:
public class UserTitlesManager : BaseManager
{
private readonly UserTitlesOperations _userTitlesOperations;
public UserTitlesManager()
{
_userTitlesOperations = new UserTitlesOperations(base.IUOW);
}
public List<UserTitlesWM> GetAllUserTitles()
{
try
{
return UserTitlesMapping.MaptoWM(_userTitlesOperations.GetAllUserTitles());
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
}
Finally, this is my API Controller:
[Route("api/LoginRequest")]
public class TitlesController : BaseController
{
UserTitlesManager _userTitlesManager;
public LoginController()
{
_userTitlesManager = new UserTitlesManager();
}
[Route("RetreiveTitles")]
public HttpResponseMessage GetTitles()
{
try
{
return Request.CreateResponse(HttpStatusCode.OK, _userTitlesManager.GetAllUserTitles());
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.ToString());
}
}
}
By the way BaseController is just another API controller which gives inheritance to all other API controllers, and houses a method which is used by all the other controllers.
So, I'm still trying to sharpen my self on this design patterns and would be glad if anyone could show my mistake on BaseManager class. As I said, I suppose the problem is caused by that private readonly XaPaDataContext _context; line. On the other hand,I can't figure out how to corrrect it as my operation classes' constructors are asking for IUnitOfWork.
Thank you in advance!
EDIT:
Just realized that I forgot to share my Unit of Work class:
public class XaPaUnitOfWork : IUnitOfWork
{
private readonly XaPaDataContext _context;
public XaPaUnitOfWork(XaPaDataContext context)
{
_context = context;
Categories = new CategoriesRepository(_context);
OrderDetails = new OrderDetailsRepository(_context);
Orders = new OrdersRepository(_context);
ProductImages = new ProductImagesRepository(_context);
Products = new ProductsRepository(_context);
Users = new UsersRepository(_context);
UserTitles = new UserTitlesRepository(_context);
UserTokens = new UserTokensRepository(_context);
}
public ICategoriesRepository Categories { get; private set; }
public IOrderDetailsRepository OrderDetails { get; private set; }
public IOrdersRepository Orders { get; private set; }
public IProductImagesRepository ProductImages { get; private set; }
public IProductsRepository Products { get; private set; }
public IUsersRepository Users { get; private set; }
public IUserTitlesRepository UserTitles { get; private set; }
public IUserTokensRepository UserTokens { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
After I have changed my BaseManager class as below:
public abstract class BaseManager
{
private IUnitOfWork _iUow;
public IUnitOfWork IUOW
{
get
{
if (_iUow == null)
{
_iUow = new XaPaUnitOfWork(new XaPaDataContext());
}
return _iUow;
}
}
}
I have achived to receive HttpStatusCode.OK
But, honestly, I'm still unsure about the real reason. I make this correction mostly by heart.
I am trying to create DBContect object by passing connection string at run time.
Following is the structure of my NiNject Repository implementation.
public class HomeController : ApiController
{
MyService _service{ get; set; }
public HomeController(MyService service)
{
_service= service;
}
}
public class MyService
{
IRepository _repo { get; set; }
public MyService(IRepository repo)
{
_repo = repo;
}
}
Repository implementation is as follows :
public interface IRepository
{
TenantDbContext _db { get; set; }
void Add<T>(T entity) where T : class;
void Delete<T>(int id) where T : class;
T Find<T>(int id) where T : class;
IQueryable<T> Query<T>() where T : class;
void SaveChanges();
MasterDbContext _db_master { get; set; }
void Add_Master<T>(T entity) where T : class;
void Delete_Master<T>(int id) where T : class;
T Find_Master<T>(int id) where T : class;
IQueryable<T> Query_Master<T>() where T : class;
void SaveChanges_Master();
}
public class Repository : IRepository
{
public TenantDbContext _db { get; set; }
public MasterDbContext _db_master { get; set; }
public Repository(TenantDbContext db)
{
_db = db;
}
public Repository(MasterDbContext db_master)
{
_db_master = db_master;
}
public IQueryable<T> Query<T>() where T : class
{
return _db.Set<T>().AsQueryable();
}
public IQueryable<T> Query_Master<T>() where T : class
{
return _db_master.Set<T>().AsQueryable();
}
//.....Rest of the implemetation
}
Here goes my TenantDBContext class which takes an argument as a database string. No default constructor
public class TenantDbContext : DbContext
{
public TenantDbContext(string connString)
: base(connString)
{
//Configuration.AutoDetectChangesEnabled = true;
//Configuration.LazyLoadingEnabled = false;
//Configuration.ProxyCreationEnabled = false; //change tracking
}
public static TenantDbContext Create(string DbString)
{
// Some logic to get the tenant database string.
// Presently i am just passing it hard coded as follows.
return new TenantDbContext(DbString);
}
}
public class MasterDbContext : IdentityDbContext<ApplicationUser>
{
public MasterDbContext() : base("MasterDBConnection", throwIfV1Schema: false)
{
// dbmigration.AutomaticMigrationsEnabled = true;
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public static MasterDbContext Create()
{
return new MasterDbContext();
}
//public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public DbSet<TenantUserMap> TenantUserMaps { get; set; } }
Finally, RegisterServices which i have in my NinjectWebCommons.cs looks as follows :
Each Tenant have its different database. We are fetching out the Tenant name from the access token on every request and caching that requested Tenant object so we can pass the correct Tenant Database string in order to do the operations on the requested Tenant Database.
Below snippet, We are fetching the Tenant object from the current request cache which will provide us the Tenant Database string of the requested client.
public Tenant Tenant
{
get
{
object multiTenant;
if (!HttpContext.Current.GetOwinContext().Environment.TryGetValue("MultiTenant", out multiTenant))
{
throw new ApplicationException("Could Not Find Tenant");
}
return (Tenant)multiTenant;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRepository>().To<Repository>();
kernel.Bind<TenantDbContext>().ToMethod(_ =>
TenantDbContext.Create(Tenant.DBString));
kernel.Bind<MasterDbContext>().ToMethod(__ => MasterDbContext.Create());
}
Problem : When i add second binding in my NinjectWebCommons.cs "kernel.Bind()" , i start getting exception saying that "No default constructor found". It is simply not taking two bindings with the kernal. Request you to please have a look at the code above and point me out where i am going wrong.
I will appreciate your help. Thanks in Advance.
You may add a binding for the database context and point Ninject to use your factory method:
kernel.Bind<TenantDbContext>().ToMethod(_ => TenantDbContext.Create());