I've implemented repository pattern with unit of work into an MVC app. Here is the implementation:
public interface IUnitOfWork
{
IStudentRepository Students { get; }
ICourseRepository Courses { get; }
void Complete();
}`
` `
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public IStudentRepository Students { get; private set; }
public ICourseRepository Courses { get; private set; }
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
Students = new StudentRepository(_context);
Courses = new CourseRepository(_context);
}
public void Complete()
{
_context.SaveChanges();
}
}
`
My question is, when I have 100s of repositories, what is the best approach to initiate a repository?
Thanks
I found the answer from one of the comments from this video: https://www.youtube.com/watch?v=rtXpYpZdOzM
Instead of initializing repositories in constructor, I can use getters like below:
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
private ICourseRepository _courses = null;
private IStudentRepository _students = null;
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
}
public ICourseRepository Courses => _courses ?? (_courses = new CourseRepository(_context));
public IStudentRepository Students => _students ?? (_students = new StudentRepository(_context));
Related
I tried to implement the function without success
I want to check if the user's status is true so that means he is logged in
I mean if Status is false then I do not want to display it at all in a list that will be ignored
What I tried causes all the connected to be displayed even if they are false
Model:
[Table("Contact")]
public partial class Contact
{
[Key]
public Guid Id { get; set; }
public string DisplayName { get; set; } = null!;
public string ProfilePic { get; set; } = null!;
public int? Rating { get; set; }
public bool? Status { get; set; }
public bool? IsRegistration { get; set; }
}
DbContext:
public virtual DbSet<Contact> Contacts { get; set; } = null!;
Repository:
private readonly TalkBackContactsDbContext _context;
public ContactsRepository(TalkBackContactsDbContext context)
{
_context = context;
}
public IQueryable<Contact> GetAllConnectedUser(Contact contact)
{
if (contact.Status == false)
{
throw new Exception("Not exist");
}
else
{
return _context.Contacts;
}
}
api controller:
private readonly IContactsRepository _repo;
public ContactsController(IContactsRepository repo)
{
_repo = repo;
}
[HttpGet()]
public IEnumerable<Contact> GetAllConnected()
{
var contact = new Contact();
try
{
return _repo.GetAllConnectedUser(contact);
}
catch (Exception e)
{
e.ToString();
}
return _repo.GetAllConnectedUser(contact);
}
Try this.
Repository:
private readonly TalkBackContactsDbContext _context;
public ContactsRepository(TalkBackContactsDbContext context)
{
_context = context;
}
public IEnumerable<Contact> GetAllConnectedUser()
{
_context.Contacts.Where(a=>a.Status==true).AsEnumerable();
}
api controller:
private readonly IContactsRepository _repo;
public ContactsController(IContactsRepository repo)
{
_repo = repo;
}
[HttpGet()]
public IEnumerable<Contact> GetAllConnected()
{
return _repo.GetAllConnectedUser();
}
I am trying to create Generic Implementation to publish messages with MassTransit.
BasePublisher
public abstract class BasePublisher
{
private readonly IPublishEndpoint publishEndpoint;
public BasePublisher(IPublishEndpoint publishEndpoint)
{
this.publishEndpoint = publishEndpoint;
}
public Task Publish(IntegrationBaseEvent message)
{
return publishEndpoint.Publish(message);
}
}
IntegrationBaseEvent
public class IntegrationBaseEvent
{
public IntegrationBaseEvent(Guid id, string name, DateTime createdDate)
{
Id = id;
Name = name;
CreationDate = createdDate;
}
public IntegrationBaseEvent()
{
Id = Guid.NewGuid();
CreationDate = DateTime.UtcNow;
}
public Guid Id { get; private set; }
public string Name { get; set; }
public DateTime CreationDate { get; private set; }
}
And I've created events using the abstraction IntegrationBaseEvent.
public class BusinessCreatedEvent : IntegrationBaseEvent
{
public Guid BusinessId { get; set; }
public string BusinessName { get; set; }
}
With the interface below, I am trying to publish the message but it not at all consumed
public interface IPublisher
{
Task Publish(IntegrationBaseEvent message);
}
It is consumed only when I create a separate publisher for the inherited event BusinessCreatedEvent something like below
public interface ISubscriptionPublisher
{
Task Publish(BusinessCreatedEvent message);
}
I don't want to create a different publisher and just want to use the abstract publisher like below.
public class BusinessCreatedEventHandler
{
private readonly IPublisher _publisher;
public BusinessCreatedEventHandler(IPublisher publisher)
{
_publisher = publisher;
}
public Task Handle(string id, string name)
{
var message = new BusinessCreatedEvent
{
BusinessId = id,
BusinessName = name
};
_publisher.Publish(message);
return Task.CompletedTask;
}
}
Any ideas to make it generic, please?
MassTransit leverages generics extensively, and limits types to the generic type specified. Since you're specifying the base interface as the generic type in the call to Publish, that base interface type is all that is published.
Your question is similar to the this one, and my answer – and the solution is the same. Convert it to object and use the Publish(object message) overload instead. That way, MassTransit will use the object type (MassTransit will call message.GetType() and properly dispatch the message type.
Or, you could make your interface include a generic method as well:
public interface IPublisher
{
Task Publish<T>(T message)
where T : class, IntegrationBaseEvent;
}
Im my Web API project, am trying to map the id in DTO call to the Object. But I am facing issues in setting up dependecy using AutoFac.
Below is the classes I am using.
public abstract class DomainObject<IdT> : IDomainObject<IdT>
{
public virtual IdT Id { get; set; }
}
public class Course : DomainObject<long>
{
public string CourseName { get; set; }
public Teacher Teacher { get; set; }
}
public class Teacher : DomainObject<long>
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
I want to map CourseDTO to Course , the TeacherID has to be mapped to Teacher object
public class CourseDTO
{
public long Id{ get; set; }
public string CourseName { get; set; }
public long TeacherID { get; set; }
}
Below is the entity converter.
public class EntityConverter<T,IdT> : ITypeConverter<IdT, T>
{
private readonly IGenericRepository<T, IdT> _repository;
public EntityConverter(IGenericRepository<T, IdT> repository)
{
_repository = repository;
}
public T Convert(ResolutionContext context)
{
return _repository.GetById((IdT)context.SourceValue);
}
}
How can I define the mapping and inject the dependency using AutoFac.
It's not clear from your question what you are having trouble with. If you're just trying to map the TeacherId in your DTO, then there is no work to do at all:
Mapper.CreateMap<Course, CourseDTO>();
TeacherId will be mapped automatically from Teacher.Id.
If you're wanting to map a TeacherDTO by looking it up from the repository, then you can use the approach in the linked question. Registration will be very similar to the Windsor approach, and setting up the container for resolution is almost identical too:
ContainerBuilder builder = new ContainerBuilder();
var container = builder.Build();
Mapper.Initialize(cfg => cfg.ConstructServicesUsing(container.Resolve));
If you're trying to do more complicated things than this, then you'll need to post the actual DTOs you're trying to map to.
I am developing in ASP.NET MVC3 and EntityFramework.
I want my model to follow an interface :
public class Account : IAccount
{
public string Id { get; set; }
public DateTime Date { get; set; }
public string Language { get; set; }
}
public interface IAccount
{
string Id { get; set; }
DateTime Date { get; set; }
string Language { get; set; }
}
Here's my Context
public class EFContext : DbContext, IContext
{
public DbSet<Account> Accounts { get; set; }
}
And here's the repository :
public interface IRepository<T> where T : class
{
IQueryable<T> All { get; }
int Count { get; }
bool Contains(Expression<Func<T, bool>> predicate);
void Create(T item);
void Update(T item);
void Delete(Expression<Func<T, bool>> predicate);
void Delete(T item);
}
public class EFRepository<T> : IRepository<T> where T : class
{
private EFContext _context;
public EFRepository(IUnitOfWork uow)
{
this._context = (EFContext)uow.Context;
}
protected DbSet<T> DbSet
{
get
{
return _context.Set<T>();
}
}
public IQueryable<T> All
{
get
{
return DbSet.AsQueryable();
}
}
public virtual int Count
{
get
{
return DbSet.Count();
}
}
public bool Contains(Expression<Func<T, bool>> predicate)
{
return DbSet.Count(predicate) > 0;
}
public virtual void Create(T item)
{
DbSet.Add(item);
}
public virtual void Update(T TObject)
{
var item = DbSet.Attach(TObject);
_context.SetItemState(TObject, EntityState.Modified);
}
public virtual void Delete(Expression<Func<T, bool>> predicate)
{
var objects = DbSet.Where(predicate);
foreach (var obj in objects)
{
DbSet.Remove(obj);
}
}
public virtual void Delete(T TObject)
{
DbSet.Remove(TObject);
}
}
Now, I want to use IRepository<IAccount> but this will ask the context for DbSet<IAccount>. This leads to an error since the Context contains a DbSet<Account>.
I then tried the solution proposed here for Linq2Sql : http://iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx
So I added this function to my EFContext
public new DbSet<T> Set<T>() where T : class
{
var ciccio = TableMaps[typeof(T)];
return (DbSet<T>)base.Set(ciccio).Cast<T>();
}
But it doesn't work.
Do anyone have a suggestion?
Thx
What benefit are you receiving from using an interface for your entities? I don't see any value here. Typically, you use Interfaces to remove dependencies upon the implementation, but that's not what you're achieving here because you're returning a concrete DbSet of objects.
Your entities are already Poco's. They don't have dependencies on other implemntations, and they have no code in them other than a getter/setter. Using an interface is redundant and pointless.
I've found a workaround. I kind of like it so I want to share it.
I rewritten my EFRepository :
public class EFRepository<T, W> :
IRepository<T> where T : class
where W : class, T
{
private EFContext _context;
public EFRepository(IUnitOfWork uow)
{
this._context = (EFContext)uow.Context;
}
protected DbSet<W> DbSet
{
get
{
return _context.Set<W>();
}
}
public IQueryable<T> All
{
get
{
return DbSet.AsQueryable<T>();
}
}
public virtual int Count
{
get
{
return DbSet.Count();
}
}
public bool Contains(Expression<Func<T, bool>> predicate)
{
return All.Count(predicate) > 0;
}
public virtual void Create(T item)
{
DbSet.Add(item as W);
}
public virtual void Update(T TObject)
{
var item = DbSet.Attach(TObject as W);
_context.SetItemState(TObject, EntityState.Modified);
}
public virtual void Delete(Expression<Func<T, bool>> predicate)
{
var objects = All.Where(predicate);
foreach (var obj in objects)
{
DbSet.Remove(obj as W);
}
}
public virtual void Delete(T TObject)
{
DbSet.Remove(TObject as W);
}
}
So now basically all I need to do now is
IRepository<IAccount>> accRepository = new EFRepository<IAccount, Account>(uow);
I am happy with this solution, but still I'm not sure it is the best one, so any comments will be appreciated.
Thanks
In my application got:
Classes
public class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public bool IsApproved { get; set; }
}
public class DataContext : DbContext
{
DbSet<User> Users { get; set; }
}
public class Repository
{
DataContext db = new DataContext();
public bool ApproveUser(User usr) //This is correct place?
{
usr.IsApproved = true;
db.Attrach(usr);
return db.SaveChanges() > 0;
}
}
Question
Where putting logic approval user?
In Repository? In own class?
I ask this because today is the repository and am having trouble to test this once approval is the logic of production in the repository in the repository and not fake.
Repository is the place to write data access. User approval is more likely to be business process, so it better be separated from data access. I would do it this way (code below is more like of pseudocode, not the full production-ready stuff)
public interface IUserRepository
{
bool Save();
}
public class UserRepository : IUserRepository
{
public bool Save(User user)
{
db.Attrach(user);
return db.SaveChanges() > 0;
}
}
public interface IUserService
{
bool Approve(User user);
}
public class UserService : IUserService
{
readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public bool Approve(User user)
{
user.IsApproved = true;
return _repository.Save(User user);
}
}
And now, this already is the testable code