i've got many ef core entities with a possibility to join a shared child table ( without FK-s). I created a generic join extension method, but got a bit stuck returning the main parent entity with the child mapped to it.
Heres what i've got:
public interface IBaseEntity
{
int Id { get; set; }
}
public interface IBaseAttachmentEntity:IBaseEntity
{
ICollection<ResourceAttachment> ResourceAttachment { get; set; }
}
public class ResourceAttachment:BaseEntity
{
//PK- Id of the parent table
public long ParentId { get; set; }
// type or enum of a parent table. Should point to which table it points to
public string ResourceType { get; set; }
public string AttachmentType { get; set; }
public string Value { get; set; }
}
public static class EFCoreExtension
{
//this must be a generic method, want to use it for ~30 tables where the entity inherits IBaseAttachmentEntity
public static IQueryable<TEntity> IncludeResourceAttachment<TEntity>
(this IQueryable<TEntity> queryable,IServiceProvider serviceProvider) where TEntity : class,IBaseAttachmentEntity
{
var className = queryable.ElementType.Name;
var attachmentRepository = serviceProvider.GetRequiredService<IResourceAttachmentRepository>();
var attachments = attachmentRepository
.FindAllQueriable(x => x.ResourceType == className); //this part is fine
var joined = (from q in queryable
join a in attachments on q.Id equals a.ParentId into qa
from a in qa.DefaultIfEmpty()
select new {Parent=q,Attachments = qa}); // joining the child table, ending up with a tuple like result
return joined.Select(x => x.Parent); // need to return the Parent together with Parent.ResourceAttachment which id defined in the
}
}
want to use the extension like this:
var result = _deviceServiceService.FindAllQueriable(CurrentUserId(), matchFilter)
.IncludeResourceAttachment(_serviceProvider).ToList();
EDIT:
i have also created a minimal sample project to run. Uses In memory Db with data seeding
https://github.com/rauntska/EFGenericChildJoin
Thanks!
THis might not be what you want, but you might have to settle for it:
public static IEnumerable<TEntity> IncludeResourceAttachment<TEntity>
(this IQueryable<TEntity> queryable, IServiceProvider serviceProvider) where TEntity : class, IBaseAttachmentEntity
{
var className = queryable.ElementType.Name;
var dataContext = serviceProvider.GetRequiredService<DataContext>();
var attachments = dataContext.Set<ResourceAttachment>().Where(x => x.ResourceType == className);
var joined =
from q in queryable
join a in attachments on q.Id equals a.ParentId into qa
select new { Parent = q, Attachments = qa };
foreach (var x in joined)
foreach (var y in x.Attachments)
x.Parent.ResourceAttachment.Add(y);
return joined.Select(x => x.Parent);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.