I am using repository pattern and I am struggling with how to join two classes using lamda expression. What is the best approach to use GenericRepository class? I am new to this design pattern. I have seen in some site that suggest not to expose LINQ in Repository class This suggest not to expose LINQ in repository class If we don't use LINQ in repository class, what is the best option to join two tables(classes)?
I have the following tables as shown in ER diagram ER diagram for playlist
1)PlayList
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MusicCloud.Model.EFModel
{
using System;
using System.Collections.Generic;
public partial class PlayList
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public PlayList()
{
this.PlayListSongs = new HashSet<PlayListSong>();
}
public int Id { get; set; }
public string Name { get; set; }
public Nullable<System.DateTimeOffset> CreatedDate { get; set; }
public Nullable<System.DateTimeOffset> ModifiedDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PlayListSong> PlayListSongs { get; set; }
}
}
2) PlayListSong
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MusicCloud.Model.EFModel
{
using System;
using System.Collections.Generic;
public partial class PlayListSong
{
public int PUSongId { get; set; }
public int PlistId { get; set; }
public int SongId { get; set; }
public string UserId { get; set; }
public virtual AspNetUser AspNetUser { get; set; }
public virtual PlayList PlayList { get; set; }
public virtual Song Song { get; set; }
}
}
In UnitofWork class, I have
/// <summary>
///
/// </summary>
public GenericRepository<PlayList> PlayListRepository
{
get
{
if (this._playListRepository == null)
this._playListRepository = new GenericRepository<PlayList>(_context);
return _playListRepository;
}
}
/// <summary>
///
/// </summary>
public GenericRepository<PlayListSong> PlayListSongRepository
{
get
{
if (this._playListSongRepository == null)
this._playListSongRepository = new GenericRepository<PlayListSong>(_context);
return _playListSongRepository;
}
}
How do I implement something like this
namespace MusicCloud.Services
{
public class PlayListServices : IPlayListServices
{
private readonly UnitOfWork _unitOfWork;
public PlayListServices(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IEnumerable<PlayListEntity> GetAllPlayLists(string userId)
{
string[] includes = { "PlayList", "PlayListSong" };
var playLists =_unitOfWork.PlayListSongRepository.GetWithMultipleInclude(
e => e.UserId==userId,includes
).Select(x=>x.PlayList).ToList();
if (playLists.Any())
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<PlayList, PlayListEntity>(); });
var playListsModel = Mapper.Map<List<PlayList>, List<PlayListEntity>>(playLists);
return playListsModel;
}
return null;
}
}
}
I want to get all the playlists(playlist names) created by a user. How do I join Playlist and PlayListSong to filter by userId? The code below gives error.
string[] includes = { "PlayList", "PlayListSong" };
var playLists =_unitOfWork.PlayListSongRepository.GetWithMultipleInclude(
e => e.UserId==userId,includes
).Select(x=>x.PlayList).ToList();
/// <summary>
/// Inclue multiple
/// </summary>
/// <param name="predicate"></param>
/// <param name="include"></param>
/// <returns></returns>
public IEnumerable<TEntity> GetWithMultipleInclude(
System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate, string[] include)
{
IQueryable<TEntity> query = this.DbSet;
foreach (string inc in include)
{
query = query.Include(inc);
}
return query.Where(predicate).ToList<TEntity>() ;
}
Or is there a better way to achieve this only using the PlayListRepository and PlayListSongRepository only without lamda expression? What is best appropriate approach? Similaryly if I need to update multiple related tables, how do I perform the update,using lamda or just PlayListRepository and PlayListSongRepository only?
Thanks.
in PlayListSong You have
public virtual PlayList PlayList { get; set; }
The easiest way to get playLists is to enable lazy loading, and just get all playlist from play list songs.
I don't know how Your repo looks, but if You have something like this:
public IEnumerable<T>`GetAll()
{
return db.Set<T>();
}
Then just get it like this:
_unitOfWork.PlayListSongRepository.GetAll()
.Where(x => x.UserId == userId).Select(x => x.PlayList).Distinct();
Just remember to enable lazy loading.