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
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();
}
public interface IBLLRepo<T>
{
T Create(T app);
long Find(long id);
T Update(T app);
}
public class CustomTDRUser : IBLLRepo<CustomTDRUser>
{
public long UserId { get; set; }
public long? ApplicationId { get; set; }
[Required]
public string UserName { get; set; }
public long? DeptId { get; set; }
[Required]
public long? DesgnId { get; set; }
public long Find(long id)
{
throw new NotImplementedException();
}
public CustomTDRUser Create(CustomTDRUser app)
{
throw new NotImplementedException();
}
public CustomTDRUser Update(CustomTDRUser app)
{
throw new NotImplementedException();
}
}
services.AddTransient(typeof(IBLLRepo<CustomTDRUser>), typeof(CustomTDRUser));
i dont want to add each class in startup like this i want register these class dynamically which inherits genric interface
i tried many solution its throwing error
: 'Open generic service type 'TestingCore.Repositories.IBLLRepo`1[T]' requires registering an open generic implementation type. (Parameter 'descriptors)
if i use this code given below linkgithubgenericinterfacelink
You could use Scrutor for this. It’s a package that allows you to register services with the DI container based on conventions that you can define yourself.
In your case, you have a single interface IBLLRepo<T> and want to register the implementation for any T.
services.Scan(scan => scan
// look in the assembly which contains the Startup class
.FromAssemblyOf<Startup>()
// Find all classes that are an IBLLRepo
.AddClasses(classes => classes.AssignableTo(typeof(IBLLRepo<>)))
// register them as the interface they implement
.AsImplementedInterface()
// with a transient lifetime
.WithTransientLifetime()
);
So if you had the following classes:
public class CustomTDRUser : IBLLRepo<CustomTDRUser> { … }
public class CustomTDRCustomer : IBLLRepo<CustomTDRCustomer> { … }
public class CustomTDRProduct : IBLLRepo<CustomTDRProduct> { … }
then this would result in the following registrations:
services.AddTransient<IBLLRepo<CustomTDRUser>, CustomTDRUser>();
services.AddTransient<IBLLRepo<CustomTDRCustomer>, CustomTDRCustomer>();
services.AddTransient<IBLLRepo<CustomTDRProduct>, CustomTDRProduct>();
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));
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
The end goal for this post is to override the ToString() method of a concrete implementation of a generic base class while still being able to search the implementation using Linq flattening technique. So if you read this and see a better way let me know. I'm using Telerik controls for Silverlight and they won't change their api to allow some of their control properties to be data-bound and instead rely on the ToString() method of whatever object they are bound to. yea, stupid.. Anyway here is what I've got.
RadTreeView control on my page. The FullPath property of each node in the treeview uses the ToString() method of each item its bound to (so this is what I need to override).
I had to create an "intermediary" class to enhance my base model class so it can be bound as a heirarchy in the tree view and then a concrete implementation of that generic class to override ToString(). Now the problem is I have a Linq extension that explodes because it cannot convert the concrete implementation back to the base generic class. I love generics but this is too much for me. Need help on solving the extension method issue.
Intermediary generic class:
public class HeirarchicalItem<T> : NotifyPropertyChangedBase, INotifyCollectionChanged where T : class
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs ea)
{
if (CollectionChanged != null)
CollectionChanged(this, ea);
}
public HeirarchicalItem() { }
public HeirarchicalItem(T item)
{
Item = item;
}
public HeirarchicalItem(IEnumerable<T> collection)
{
CopyFrom(collection);
}
private T _item;
public T Item
{
get
{
return _item;
}
set
{
_item = value;
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Item);
}
}
private ObservableCollection<HeirarchicalItem<T>> _children = new ObservableCollection<HeirarchicalItem<T>>();
public virtual ObservableCollection<HeirarchicalItem<T>> Children
{
get { return _children; }
set
{
_children = value;
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
private void CopyFrom(IEnumerable<T> collection)
{
if ((collection != null))
{
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
HeirarchicalItem<T> newHeirarchicalItem = new HeirarchicalItem<T>(enumerator.Current);
Children.Add(newHeirarchicalItem);
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
}
}
}
}
}
Base model class: (data is shuttled to and from WCF Ria service using this class)
public class tbl_Path : EntityBase, IFullPath, IEquatable<tbl_Path>, IEqualityComparer<tbl_Path>
{
public tbl_Path();
public int GetHashCode(tbl_Path obj);
public override string ToString();
public DateTime CreateDate { get; set; }
public short Depth { get; set; }
public string FullPath { get; set; }
public bool IsAuthorized { get; set; }
public bool IsSelected { get; set; }
public string Name { get; set; }
public override IEnumerable<Operation> Operations { get; }
public int? ParentPathID { get; set; }
public int PathID { get; set; }
public Guid SecurityKey { get; set; }
public EntityCollection<tbl_Configuration> tbl_Configuration { get; set; }
public EntityCollection<tbl_Key> tbl_Key { get; set; }
public EntityCollection<tbl_SecurityACL> tbl_SecurityACL { get; set; }
public EntityCollection<tbl_SecurityInheriting> tbl_SecurityInheriting { get; set; }
public EntityCollection<tbl_Variable> tbl_Variable { get; set; }
}
Concrete Implementation so that I can override ToString():
public class HeirarchicalPath : HeirarchicalItem<tbl_Path>
{
public HeirarchicalPath()
{
}
public HeirarchicalPath(tbl_Path item)
: base(item)
{
}
public HeirarchicalPath(IEnumerable<tbl_Path> collection)
: base(collection)
{
}
public override string ToString()
{
return Item.Name; **// we override here so Telerik is happy**
}
}
And finally here is the Linq extension method that explodes during compile time because I introduced a concrete implementation of my generic base class.
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
foreach (T item in source)
{
yield return item;
IEnumerable<T> seqRecurse = fnRecurse(item);
if (seqRecurse != null)
{
foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
{
yield return itemRecurse;
}
}
}
}
Actual code that is breaking: (x.Children is highlighted with the error)
Cannot implicitly convert type
'System.Collections.ObjectModel.ObservableCollection<HeirarchicalItem<tbl_Path>>' to
'System.Collections.Generic.IEnumerable<HeirarchicalPath>'. An explicit conversion
exists (are you missing a cast?)
HeirarchicalPath currentItem = this.Paths.Traverse(x => x.Children).Where(x => x.Item.FullPath == "$/MyFolder/Hello").FirstOrDefault();
Figured it out. Been working on this all day and minutes after posting the question I resolve it as always.
Just needed to add this bit to my concrete implementation and no more compiler errors.
private ObservableCollection<HeirarchicalPath> _children = new ObservableCollection<HeirarchicalPath>();
public new ObservableCollection<HeirarchicalPath> Children
{
get
{
return _children;
}
set
{
if (value == null)
return;
_children = value;
RaisePropertyChanged<HeirarchicalPath>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}