Current user (ASP.NET Identity) information within Generic repository pattern - asp.net-core

I have implemented generic repository pattern over an EF Core context, for example;
public class GenericRepository<TEntity, TContext> : IGenericRepository<TEntity>
where TEntity : EntityBase
where TContext : DbContext
{
internal TContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(TContext context)
{
this.context = context;
dbSet = context.Set<TEntity>();
}
public virtual TEntity GetById(long id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
entity.CreatedDate = DateTime.Now;
dbSet.Add(entity);
}
//... additional methods removed for brevity
}
All my models are using an EntityBase class that allows me to record when the record was created and by whom, for example;
public abstract class EntityBase {
public long Id { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
//... additional fields removed for brevity
}
What are the different ways to access the current user within the repository, so I can add the user to the entity on creation;
public virtual void Insert(TEntity entity)
{
entity.CreatedBy = CurrentUser.Name; // TODO: get current user here?
entity.CreatedDate = DateTime.Now;
dbSet.Add(entity);
}
It feels like I should be able to do this via middleware and or injection.

I think, you should pass user information from controller to the repository method or set CreatedBy value inside the controller instead of Repository method. Moreover , in my opinion you should avoid depend your repository to the identity and keep it simple and independent.
In other words, referencing HttpContext.User.Identity inside your repository is not a good idea,and HttpContext belog to the Presentation Layer not Data Layer.

Related

Automapper profile maps its props to my dto

Hi.
I want just map entity to dto but profile props map to the dto.
Now what can i do for the following problem?
public abstract class DtoProfile<TEntity, TDto> : Profile, IProfile
{
public DtoProfile()
{
var profile = CreateMap<TEntity, TDto>();
CustomMapping(profile);
}
public virtual void CustomMapping(IMappingExpression<TEntity, TDto> mapping)
{
}
}
public class UserDto : DtoProfile<Users,UserDto>
{
public int Id { get; set; }
public string FullName { get; set; }
public string NationalCode { get; set; }
public DateTime CreatedDate { get; set; }
}
You're doing this in a wrong way. Mapping Profiles should be for mapping, and not to be inherited from the Dto itself.
You're inherting from Profile in DtoProfile, and these properties are defined in Profile, so they will be there. And as the name of class, it's for mapping profile, and shouldn't be used for Dto.
You should have two classes, one is UserDto where you add all the properties you need to map, and the other is UserDtoProfile which inherits from DtoProfile<User, UserDto> and apply your mappings.

Strategy Design Pattern and EF Core

I should implement strategy design pattern and I was thinking about what the right way is. Let's say I have the following example below.
I know Discriminator is able to do that on EF Core level but I should take off the inheritance for that case (Mapping inheritance in EntityFramework Core). What is the best practice? If you look in that other thread I linked, there is a solution with HasDiscriminator but I don't know about the inheritance.
public abstract class Strategy
{
public int Id { get; set; }
public string Name { get; set; }
public abstract void SomeLogic();
}
public class FirstStrategy : Strategy
{
public string CustomField { get; set; }
public override void SomeLogic()
{
throw new NotImplementedException();
}
}
public class SecondStrategy : Strategy
{
public int CustomValue { get; set; }
public override void SomeLogic()
{
throw new NotImplementedException();
}
}
The strategy pattern is about behavior, while Entity Framework Core deals with data.
To persist an inheritance hierarchy with EF it should be fine sticking with the default pattern without customizing the discriminator (if that is what you want to avoid). See Inheritance for further information.

Create a Parent with existing children in EntityFramework core

I am building a Web API and have two models: Task and Feature:
public class Feature
{
[Key]
public long FeatureId { get; set; }
public string Analyst_comment { get; set; }
public virtual ICollection<User_Task> Tasks { get; set; }
public Feature()
{
}
}
public class User_Task
{
[Key]
public long TaskId { get; set; }
public string What { get; set; }
[ForeignKey("FeatureId")]
public long? FeatureId { get; set; }
public User_Task()
{
}
}
I create Tasks first and then create a Feature that combines few of them. Task creation is successful, however while creating a Feature with existing Tasks, my controller throws an error saying the task already exists:
My FeatureController has following method:
//Create
[HttpPost]
public IActionResult Create([FromBody] Feature item)
{
if (item == null)
{
return BadRequest();
}
** It basically expects that I am creating a Feature with brand new tasks, so I guess I will need some logic here to tell EF Core that incoming tasks with this feature already exist **
_featureRepository.Add(item);
return CreatedAtRoute("GetFeature", new { id = item.FeatureId }, item);
}
How to tell EF core that incoming Feature has Tasks that already exist and it just needs to update the references instead of creating new ones?
My context:
public class WebAPIDataContext : DbContext
{
public WebAPIDataContext(DbContextOptions<WebAPIDataContext> options)
: base(options)
{
}
public DbSet<User_Task> User_Tasks { get; set; }
public DbSet<Feature> Features { get; set; }
}
And repo:
public void Add(Feature item)
{
_context.Features.Add(item);
_context.SaveChanges();
}
When calling Add on a DBSet with a model that was not loaded from EF, it thinks it is untracked and will always assume it is new.
Instead, you need to load the existing record from the dbcontext and map the properties from the data passed into the API to the existing record. Typically that is a manual map from parameter object to domain. Then if you return an object back, you would map that new domain object to a DTO. You can use services like AutoMapper to map the domain to a DTO. When you're done mapping, you only need to call SaveChanges.
Generally speaking, loading the record and mapping the fields is a good thing for the security of your API. You wouldn't want to assume that the passed in data is pristine and honest. When you give the calling code access to all the properties of the entity, you may not be expecting them to change all the fields, and some of those fields could be sensitive.

Entity Framework Many to many saving create existing entity

I have two classes with a Many-to-Many relationship. When I save my context, Entity Framework is not using the existing Ids, it creates new entry in my database.
My classes are the following : Country and CountryGroup (in my database EF creates as expected CountryGroupCountries).
public class Country : EntityBase
{
public Country()
{
CountryGroups = new List<CountryGroup>();
}
public virtual List<CountryGroup> CountryGroups { get; set; }
}
public class CountryGroup : EntityBase
{
public CountryGroup()
{
Countries = new List<Country>();
}
public virtual List<Country> Countries { get; set; }
}
public abstract class EntityBase
{
public EntityBase()
{
DateCreate = DateTime.Now;
DateUpdate = DateTime.Now;
DateDelete = DateTime.Now;
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
[Required]
public virtual String Name { get; set; }
}
I use ASP MVC 4 and Entity Framework 5. When I want to save a CountryGroup, I use Countries that are already in my website. The Ids are the right one.
public virtual void Save(TEntity entity)
{
EntityRepository.Insert(entity);
Context.SaveChanges();
}
I just want EF to save my object and the relation to the countries but not. What solution do I have here ? I Feel like I have a misunderstanding of the way EF manages Many To Many.
After many research I believe that my problem lies on the model binder. It must be only creating object without getting them from the context. I overridded my Save Method to replace each Countries in the CountryGroup entity with a fresh one from the context. It is not optimal but I'm going to studie the model binding and then I will arbitrate between those solutions.

Dynamic Proxy : wrapping constructors

I'm taking a stab at creating a Active Record implementation (I know about Castle's initiative, and it's very good) for another type of data provider (ESRIs geodatabases, using ESRIs .NET libraries) and I'm reaching something interesting.
I have a question nevertheless. I have my ActiveRecord classes which is like this:
public interface IActiveRecord<T> : IActiveRecord where T : class
{
T Create();
void Update(T record);
void Delete(T record);
}
public interface IActiveRecord
{
int ObjectId { get; set; }
bool Managed { get; }
bool IsValid { get; }
IObject EsriObject { get; set; }
IGeometry Geometry { get; set; }
void Save();
void Delete();
}
I have static Create methods, which go to DynamicProxy and generate me a proxy. But how I can enforce that the instance generated for a inheriting class is proxied too?
public class ActiveRecord<T> : IActiveRecord where T : IActiveRecord,new()
{
// protected constructors
public static T Create(IObject obj)
{
var record = Create();
record.EsriObject = obj;
return (T)record;
}
}
// inherited class
[Workspace(#"C:\teste.gdb")]
[Table("TB_PARCEL",Geometry=esriGeometryType.esriGeometryPolygon)]
public class Parcel : ActiveRecord<Parcel>,IParcel
{
[Field(4, "NM_PARCEL_ID", esriFieldType.esriFieldTypeString)]
public virtual string ParcelId { get; set; }
[Field(5, "NR_PARCEL_NO", esriFieldType.esriFieldTypeInteger)]
public virtual int StreetNumber { get; set; }
public virtual IOwner ParcelOwner { get; set; }
}
Take a look at the tests. The first three tests get intercepted as usual, but not the fourth test. I need A) prevent the user from instancing it's own classes (bad approach for the API in my opinion) or find a way to return from the inherited classes constructors the proxies.
[TestMethod]
public void ActiveRecordConstructor()
{
Parcel p1 = Parcel.Create();
Assert.IsFalse(p1.Managed);
Assert.AreEqual(null, p1.ParcelId);
Parcel p2 = Parcel.Create(2);
Assert.IsFalse(p2.Managed);
IObject fake = _repository.StrictMock<IObject>();
using (_repository.Record())
{
fake.Stub(x => x.get_Value(4)).Return("teste");
}
using (_repository.Playback())
{
Parcel p3 = Parcel.Create(fake);
Assert.IsTrue(p3.Managed);
Assert.AreEqual("teste", p3.ParcelId);
}
// this wont be intercepted
Parcel p4 = new Parcel();
Assert.IsFalse(p4.Managed);
Assert.IsNull(p4.ParcelId);
}
In short I need that whenever a user creates a new Class(), it returns a proxied object. Is that possible while allowing inheritance?
Thanks!
DynamicProxy cannot intercept calls to constructors. It has to control the creation of the object.