Hi I have been trying to change the shape of one data structure into another for a few days with no luck.
The original data structure is as follows.
public class Role : IdentityRole
{
public string Name { get; set; }
public virtual List<PermissionInRole> PermissionsInRole { get; set; }
}
public class PermissionInRole
{
public Guid Id { get; set; }
public virtual Permission Permission { get; set; }
public virtual Feature Feature { get; set; }
}
public class Permission
{
public Guid Id { get; set; }
public string Description { get; set; }
}
public class Feature
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual Application Application { get; set; }
}
public class Application
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual List<Feature> Features { get; set; }
}
I would like to use Linq to change it to this shape.
public class ApplicationApiModel
{
public string Name { get; set; }
public ICollection<FeaturesApiModel> Features { get; set; }
}
public class FeaturesApiModel
{
public string Name { get; set; }
public IEnumerable<PermissionsApiModel> Permissions { get; set; }
}
public class PermissionsApiModel
{
public string PermissionName { get; set; }
public IEnumerable<Role> Role { get; set; }
}
public class Role
{
public string Name { get; set; }
}
I would like to have a Collection of Applications, that contains a Collection of Features, that contains a collection of permissions , that contains a collection of roles that have the parent permission.
I am sure that this can be done with linq however I have not managed any help would be great.
After many attempts i ended up with following working code
var query = from role in roles
group role by role.PermissionsInRole
into g
select new
{
PinR = g.Key,
role = g.ToList()
};
var transferList = (from w in query
from pr in w.PinR
select new
{
Feature = pr.Feature, Permission = pr.Permission, TransferRole = w.role.Single()
})
.ToList()
.GroupBy(o => o.Feature, (key, o) =>
new FeaturesApiModel
{
Name = key.Name,
Permissions = o.GroupBy(transferObject => transferObject.Permission, (subKey,transferObject) =>
new PermissionsApiModel
{
PermissionName = subKey.Description,
Role = transferObject.Select(flatTransferObject => new RoleAPIModel {Name = flatTransferObject.TransferRole.Name})
}
)
});
Related
here i have a group containing many users and assets ,i want list of assets linked to a single user.
What is the best way of using linq.
public class Asset
{
public Guid Id { get; set; }
public virtual ICollection<GroupToAssets> GroupToAssets { get; set; }
}
public class User: IdentityUser
{
public virtual ICollection<GroupToUsers> GroupToUsers { get; set; }
}
public class GroupToAssets
{
public Guid GroupId { get; set; }
public virtual Group Group { get; set; }
public Guid AssetId { get; set; }
public virtual Asset Asset { get; set; }
}
public class GroupToUsers
{
public Guid GroupId { get; set; }
public virtual Group Group { get; set; }
public string UserId { get; set; }
public virtual User User { get; set; }
}
I think the following linq satisfy my case don't know if there is a better method
var Groups =
await _Context.Groups.Where(x => x.GroupToUsers.Any(d => d.UserId == UserId && d.GroupId == x.Id)).ToListAsync();
var assets =
await _Context.GroupToAssets.Where(x => Groups.Contains(x.Group)).Select(x => new { x.Asset }).Distinct().ToListAsync();
I have an implicit one to many relationship set up between Template and TemplateParameters. As far as I can tell, I am following conventions. However, when I save a Template, the children are not discovered and saved with it.
public class Template
{
#region Properties
public int TemplateId { get; set; }
public string UserId { get; set; }
public DateTime Created { get; set; }
public DateTime Published { get; set; }
public bool Deleted { get; set; }
public int Likes { get; set; }
public int Shares { get; set; }
public int Downloads { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
#endregion
#region Navigation
//navigation properties
public ApplicationUser User { get; set; }
public IEnumerable<Wave> Waves { get; set; }
public IEnumerable<TemplateParameter> TemplateParameters;
public IEnumerable<ApplicationUser> Subscribers;
#endregion
}
public class TemplateParameter
{
public int TemplateParameterId { get; set; }
public int TemplateId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double? Value { get; set; }
public DateTime Created { get; set; }
//navigation properties
public virtual Template Template { get; set; }
}
[HttpPost]
[Route("SaveTemplate")]
public TemplateViewModel SaveTemplate([FromBody] TemplateViewModel vm)
{
//get the current userId
var user = _userManager.GetUserAsync(HttpContext.User).Result;
var token = User;
//map params
var parameters = vm.Parameters.Select(r => new TemplateParameter()
{
Name = r.Name,
Description = r.Description,
Created = DateTime.Now,
}).ToList();
//map the vm to the model
var template = new Template()
{
Name = vm.Name,
Description = vm.Description,
Created = DateTime.Now,
UserId = user.Id,
TemplateParameters = parameters,
};
//save the template
template = _templateService.SaveTemplate(template);
//map id back to the view model
vm.TemplateID = template.TemplateId;
return vm;
}
public Template SaveTemplate(Template template)
{
_context.Templates.Add(template);
_context.SaveChanges();
return template;
}
Can anyone spot what I'm doing wrong here? The template saves fine, but the child collections does not. I'm using the same pattern elsewhere in my project and it seems to work without issue. Thank you in advance for your help.
Whether it is possible so: it is a Messenger where the entity User content ICollection User that are collection Friends consist from the same Users?
If that possible please tell me how create a correct relationship between them in the DbContext file?
Or how better build this relationship. May be create separate entity?
Thanks in advance!
namespace Tinkl.Data.Core.Domain
{
public class User
{
public User()
{
Contacts = new List<User>();
Conversations = new List<Conversation>();
Invites = new List<User>();
}
public int UserId { get; set; }
public string NickName { get; set; }
public string EMail { get; set; }
public string Password { get; set; }
public DateTime? CreationDate { get; set; }
public DateTime? ExitDate { get; set; }
public string Picture { get; set; }
public string Status { get; set; }
public virtual ICollection<User> Invites { get; set; }
public virtual ICollection<User> Contacts { get; set; }
public virtual ICollection<Conversation> Conversations { get; set; }
}
}
You are going in right direction, see my below code same type of self-relationship in EF code first
public class ContentEntityRef : BaseModel
{
public ContentEntityRef()
{
RoleRefs = new HashSet<RoleRef>();
}
public int EntityId { get; set; }
public string EntityName { get; set; }
public int? ParentEntityId { get; set; }
public virtual ICollection<RoleRef> RoleRefs { get; set; }
public virtual ContentEntityRef Parent { get; set; }
public virtual ICollection<ContentEntityRef> Children { get; set; }
}
I had created seprate configuration file, you can same use in dbContext "OnModelCreating" method.
internal class ContentEntityRefConfiguration : EntityTypeConfiguration<ContentEntityRef>, IEntityConfiguration
{
public ContentEntityRefConfiguration()
{
this.HasKey(x => x.EntityId).Property(t => t.EntityId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(x => x.EntityName).IsRequired().HasMaxLength(50);
this.HasMany(c => c.Children).WithOptional(c => c.Parent).HasForeignKey(c => c.ParentEntityId);
this.HasMany<RoleRef>(role => role.RoleRefs)
.WithMany(content => content.ContentEntities)
.Map(contentRole =>
{
contentRole.MapLeftKey("EntityID");
contentRole.MapRightKey("RoleID");
contentRole.ToTable("RoleEntityMap");
});
}
}
hope this will help you :)
I have article and author classes.
Fetch articles like so and map entity to model:
public List<Model.Article> GetArticleList() {
using (var db = new ArticlesContext()) {
return db.Articles.Select(t => new Model.Article() {
Author = MapUserEntityToModel(db.Users.FirstOrDefault(u => u.UserID == t.UserID))
Title = t.Title,
Teaser = t.Teaser
// etc
}).ToList();
}
}
This doesn't work because LINQ can't run that function at run-time. What's the simplest and cleanest way to do the mapping?
Here are models:
namespace Model {
public class Article {
public string Title { get; set; }
public string Teaser { get; set; }
public User Author { get; set; }
public DateTime DateAdded { get; set; }
}
public class User {
public string DisplayName { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string PasswordHash { get; set; }
}
}
Here are entities:
namespace MyProj {
public class Article {
[Key]
public int ArticleID { get; set; }
public string Title { get; set; }
public string Teaser { get; set; }
public int UserID { get; set; }
public DateTime DateAdded { get; set; }
}
public class User {
[Key]
public int UserID { get; set; }
public string DisplayName { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string PasswordHash { get; set; }
}
public class ArticleContext : DbContext {
public ArticleContext() : base("name=conn") {
public DbSet<Article> Articles { get; set; }
public DbSet<User> Users { get; set; }
}
}
}
Before continue, map your relationship in a navigation property:
public class Article {
[Key]
public int ArticleID { get; set; }
public string Title { get; set; }
public string Teaser { get; set; }
[ForeignKey("UserID")]
public virtual User Author {get; set; } // navigation property
public int UserID { get; set; }
public DateTime DateAdded { get; set; }
}
And then just project your navigation property to his equivalent Model:
public List<Model.Article> GetArticleList() {
using (var db = new ArticlesContext()) {
return db.Articles.Select(t => new Model.Article() {
Author = new Model.User {
DisplayName = t.User.DisplayName,
Email = t.User.Email,
Website = t.User.Website,
PasswordHash = t.User.PasswordHash
},
Title = t.Title,
Teaser = t.Teaser
// etc
}).ToList();
}
}
You don't need to do anything, just return db.Articles directly:
using Model;
public List<Article> GetArticleList() {
using(var db = new ArticlesContext()) {
return db.Articles.ToList();
}
}
Assuming your EF model is set-up correctly with Foreign Keys, your Article type will have a lazily-evaluated Author property which will return a User object when accessed.
I'm currently creating a Windows 8.1 app connected to an Azure Mobile Service and using EF6 Code First to create the database.
The tables currently are Account, User, Business, ProfilePicture and Blob. When a profile is created, an entry will be inserted into the Account table, and then depending on the user's selection, an entry into the User or Business table.
When an Account is instantiated, a new User or Business, and ProfilePicture models are created within the Account model.
The way I intend on implementing the ProfilePicture is to have a default profile picture set when an Account is created, therefore I select the default profile picture blob from the table and use it when creating the ProfilePicture model within the Account. The issue I'm having is that when passing in the Blob returned from the query, it seems to also insert the blob into the Blob table, thus duplicating the entry, and I've no idea why. (Hopefully this will be a bit clearer with the App.xaml.cs code below)
I'm not sure at all why this is happening. Still getting to grips with FluentAPI so my knowledge isn't the best, so any tips/guidance, as well as help, would be much appreciated! Thanks.
(sorry there's so much code)
Service Side
DataObjects
public class Account : EntityData
{
public string Username { get; set; }
public string Password { get; set; }
public User User { get; set; }
public Business Business { get; set; }
public ProfilePicture ProfilePicture { get; set; }
}
public class Business : EntityData
{
public string Name { get; set; }
public string ContactNo { get; set; }
public Account Account { get; set; }
}
public class User : EntityData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Account Account { get; set; }
}
public class ProfilePicture : EntityData
{
public Account Account { get; set; }
public Blob Blob { get; set; }
}
public class Blob : EntityData
{
public string ContainerName { get; set; }
public string ResourceName { get; set; }
public string SASQueryString { get; set; }
public string ImageURI { get; set; }
}
Entity Configurations (Only their constructors):
public AccountConfig()
{
HasKey(account => account.Id);
Property(account => account.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(account => account.Password).IsRequired();
Property(account => account.Username).IsRequired();
}
public BusinessConfig()
{
Property(business => business.ContactNo).IsRequired();
Property(business => business.Name).IsRequired();
HasRequired(business => business.Account)
.WithOptional(account => account.Business)
.WillCascadeOnDelete();
}
public UserConfig()
{
Property(user => user.FirstName).IsRequired();
Property(user => user.LastName).IsRequired();
HasRequired(user => user.Account)
.WithOptional(account => account.User)
.WillCascadeOnDelete();
}
public ProfilePictureConfig()
{
HasRequired(profile => profile.Account).
WithRequiredDependent(account => account.ProfilePicture).
WillCascadeOnDelete();
HasRequired(profile => profile.Blob);
}
public BlobConfig()
{
HasKey(blob => blob.Id);
Property(blob => blob.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(blob => blob.ContainerName).IsRequired();
Property(blob => blob.ImageURI).IsRequired();
Property(blob => blob.ResourceName).IsRequired();
Property(blob => blob.SASQueryString).IsRequired();
}
Client Side
Models
public class Account
{
public string Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public User User { get; set; }
public Business Business { get; set; }
public ProfilePicture ProfilePicture { get; set; }
}
public class Business
{
public string Id { get; set; }
public string Name { get; set; }
public string ContactNo { get; set; }
}
public class User
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class ProfilePicture
{
public string Id { get; set; }
public Account Account { get; set; }
public Blob Blob { get; set; }
}
public class Blob
{
public string Id { get; set; }
public string ContainerName { get; set; }
public string ResourceName { get; set; }
public string SASQueryString { get; set; }
public string ImageURI { get; set; }
}
App.xaml.cs
Blob blob1 = new Blob
{
ContainerName = "Container1",
ImageURI = "Uri1",
ResourceName = "DefaultProfilePic",
SASQueryString = "SomethingGoesHere"
};
await BlobTable.InsertAsync(blob1);
List<Blob> pictures = await BlobTable.Where(blob => blob.ContainerName == "Container1").ToListAsync();
Account account = new Account
{
Username = "User123",
User = new User
{
FirstName = "John",
LastName = "Smithy"
},
ProfilePicture = new ProfilePicture
{
Blob = pictures.First()
},
Password = "Password123"
};
string result = await MobileService.InvokeApiAsync<Account, string>("customAccount", account);