How to fetch an attributes from my class with EF - c#

I have 3 class, 2 are simple class and 1 combines the two of them.
public class Person:Base
{
public DateTime DOB { get; set; }
public string first { get; set; }
public string last { get; set; }
}
public class Roles:Base
{
public string Description { get; set; }
}
public class RolePerson:Base
{
public int pID { get; set; }
public virtual Person PersonID { get; set; }
public int rID { get; set; }
public virtual Roles RoleID { get; set; }
public int order { get; set; }
}
Now I have method that would select RolePerson witch would grab all member of pID with the id that i provide in the argument, and return the RoleID field.
this is how my method look like
public IEnumerable<Roles> PersonRoles(int personID)
{
return db.RolePerson.Where<RolePerson>((p) => p.pID == personID);
}
How can i say to return the role and not the roleperson.
Update:
My base class is as follow
public abstract class Base
{
public int ID { get; set; }
public Boolean isValid { get; set; }
public DateTime createdOn { get; set; }
public int createdID { get; set; }
public Person createdPerson { get; set; }
public DateTime updatedOn { get; set; }
public int updatedID { get; set; }
public Person updatedPerson { get; set; }
}

You can run a select statement in the end.
return d.RolePerson.Where(p => p.PId == personID).Select(r=> r.RoleID);

Related

Get All data from two tables in .net 5 web api?

Patient.cs //This is Patient Model Class
namespace HMS.Models
{
public class Patient
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public int age { get; set; }
public int Weight { get; set; }
public string Gender { get; set; }
public string Address { get; set; }
public string PhoneNo { get; set; }
public string Disease { get; set; }
[JsonIgnore]
public IList<DoctorPatient> DoctorPatients { get; set; }
public InPatient InPatients { get; set; }
public OutPatient OutPatients { get; set; }
}
}
InPatient.cs //This InPatient Model Class
namespace HMS.Models
{
public class InPatient
{
[ForeignKey("Patient")]
public string InPatientId { get; set; }
public string RoomNo { get; set; }
public DateTime DateOfAddmission { get; set; }
public DateTime DateOfDischarge { get; set; }
public int Advance { get; set; }
public string LabNo { get; set; }
public Patient Patient { get; set; }
}
}
Here Patient and InPatient Attribute have one-to-one relationship
ViewInPatient.cs
namespace HMS.Models
{
public class ViewInPatient
{
public string Name { get; set; }
public int age { get; set; }
public int Weight { get; set; }
public string Gender { get; set; }
public string Address { get; set; }
public string PhoneNo { get; set; }
public string Disease { get; set; }
public string RoomNo { get; set; }
public DateTime DateOfAddmission { get; set; }
public DateTime DateOfDischarge { get; set; }
public int Advance { get; set; }
public string LabNo { get; set; }
}
}
Here is my DbContext class
public class ApplicationDbContext:DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options):base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<DoctorPatient>()
.HasOne(x => x.Doctor)
.WithMany(dp => dp.DoctorPatients)
.HasForeignKey(di => di.DoctorId);
modelBuilder.Entity<DoctorPatient>()
.HasOne(y => y.Patient)
.WithMany(dp => dp.DoctorPatients)
.HasForeignKey(pi => pi.PatientId);
}
public DbSet<Patient> Patients { get; set; }
public DbSet<Doctor> Doctors { get; set; }
public DbSet<DoctorPatient> DoctorPatients { get; set; }
public DbSet<InPatient> InPatients { get; set; }
//public DbQuery<ViewInPatient> ViewInPatients { get; set; }
}
How to get all data of both Patients and InPatients Table like in ViewInPatient class? (I tried to create a view in sql server but in add table window it shows InPatient instead of InPatients and it return null value)
You can join both models in a Linq expression and return ViewInPatient list:
var ViewInPatient_set =
YourContext
.InPatients
.Select(i=> new ViewInPatient()
{
Name = i.Patient.Name,
// ...
RoomNo = i.RoomNo,
// ...
}
)
.ToList(); // <-- transform to list is optional

Why, when I pass an entity via generic, are attributes duplicated and not what is needed is stored in the database?

I have a NestedSetBuilder class. It has a MakeRootAsync method:
public async Task<TEntity> MakeRootAsync<TEntity>(TEntity ownerNode) where TEntity: NestedSetEntity
{
_operation = OperationMakeRoot;
ownerNode.Lft = 1;
ownerNode.Rgt = 2;
ownerNode.Depth = 0;
await _db.Set<TEntity>().AddAsync(ownerNode);
await _db.SaveChangesAsync();
return ownerNode;
}
There is a base class NestedSetEntity:
public class NestedSetEntity
{
public Guid Id { get; set; }
public int Lft { get; set; }
public int Rgt { get; set; }
public int Depth { get; set; }
public Guid? Tree { get; set; }
}
There is a child class Category:
[Table("categories")]
public class Category: NestedSetEntity
{
public Category()
{
Visible = true;
CreatedAt = DateTime.Now;
UpdatedAt = DateTime.Now;
}
[Column("id")]
public Guid Id { get; set; }
[Required]
[StringLength(256)]
[Column("title")]
public string Title { get; set; }
[Column("lft")]
public int Lft { get; set; }
[Column("rgt")]
public int Rgt { get; set; }
[Column("depth")]
public int Depth { get; set; }
[Column("tree")]
public Guid? Tree { get; set; }
[Column("visible")]
public bool Visible { get; set; }
[Required]
[Column("created_at")]
public DateTime CreatedAt { get; set; }
[Column("updated_at")]
public DateTime UpdatedAt { get; set; }
}
There is a method where makeRootAsync is called
[HttpGet]
public async Task<IActionResult> Categories()
{
//var res = await _dnsParserService.ParseCategoriesAsync();
var res = await _categoryParserService.ParseCategoryListAsync();
var categoryIds = new Dictionary<string, string>();
foreach (var categoryListResItem in res)
{
if (categoryIds.TryGetValue(categoryListResItem.CategoryFirstTitle, out var parentCategory))
continue;
var node = Map(categoryListResItem, "CategoryFirstTitle");
var addedCategory = await _nestedSetBuilder.MakeRootAsync(node); // this call
categoryIds[categoryListResItem.CategoryFirstTitle] = addedCategory.Id.ToString();
}
return Ok(res);
}
In the database, columns Lft, Rgt, Depth have values of zero:
In the debugger, you can see that the fields are duplicated (separately, the fields of the base class and child class):
Tell me how to fix it? I use the base class to work with LINQ
This is likely due to the fact that the properties in your derived class hide the properties in your base class. Based on what you need, I'd recommend setting the Column attributes on your base class, and remove the derived class properties:
public class NestedSetEntity
{
[Column("id")]
public Guid Id { get; set; }
[Column("lft")]
public int Lft { get; set; }
[Column("rgt")]
public int Rgt { get; set; }
[Column("depth")]
public int Depth { get; set; }
[Column("tree")]
public Guid? Tree { get; set; }
}
[Table("categories")]
public class Category: NestedSetEntity
{
public Category()
{
Visible = true;
CreatedAt = DateTime.Now;
UpdatedAt = DateTime.Now;
}
[Required]
[StringLength(256)]
[Column("title")]
public string Title { get; set; }
[Column("visible")]
public bool Visible { get; set; }
[Required]
[Column("created_at")]
public DateTime CreatedAt { get; set; }
[Column("updated_at")]
public DateTime UpdatedAt { get; set; }
}
If you need different column names for the different tables that inherit from NestedSetEntity, you can use an interface rather than a base class:
public interface NestedSetEntity
{
Guid Id { get; set; }
int Lft { get; set; }
}
[Table("categories")]
public class Category : NestedSetEntity
{
[Required]
[Column("title")]
public string Title { get; set; }
[Column("id")]
public Guid Id { get; set; }
[Column("lft")]
public int Lft { get; set; }
}
[Table("mytable")]
public class MyTable : NestedSetEntity
{
[Column("my_id")]
public Guid Id { get; set; }
[Column("left_column")]
public int Lft { get; set; }
}

Automapper many to many mapping confusion

I have many to many relationship tables such as "User & Notification & UserNotification" and their entities, view models also.
There is only a difference between ViewModel and Entity classes. HasRead property is inside NotificationViewModel. How Can I map this entities to view models? I could not achieve this for HasRead property.
What I did so far is,
Mapping Configuration:
CreateMap<Notification, NotificationViewModel>();
CreateMap<User, UserViewModel>().ForMember(dest => dest.Notifications, map => map.MapFrom(src => src.UserNotification.Select(x => x.Notification)));
Notification class:
public class Notification : IEntityBase
{
public Notification()
{
this.UserNotification = new HashSet<UserNotification>();
}
public int Id { get; set; }
public string Header { get; set; }
public string Content { get; set; }
public System.DateTime CreateTime { get; set; }
public bool Status { get; set; }
public virtual ICollection<UserNotification> UserNotification { get; set; }
}
User Class
public class User : IEntityBase
{
public User()
{
this.UserNotification = new HashSet<UserNotification>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public bool Status { get; set; }
public virtual ICollection<UserNotification> UserNotification { get; set; }
}
UserNotification class:
public class UserNotification : IEntityBase
{
public int Id { get; set; }
public int UserId { get; set; }
public int NotificationId { get; set; }
public bool HasRead { get; set; }
public virtual Notification Notification { get; set; }
public virtual User User { get; set; }
}
UserViewModel class
public class UserViewModel : IValidatableObject
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public bool Status { get; set; }
public IList<NotificationViewModel> Notifications { get; set; }
}
NotificationViewModel class
public class NotificationViewModel
{
public int Id { get; set; }
public string Header { get; set; }
public string Content { get; set; }
public System.DateTime CreateTime { get; set; }
public bool Status { get; set; }
public bool HasRead { get; set; } // this is the difference
}
In order to fix up the HasRead, maybe you can utilize the AfterMap(Action<TSource, TDestination> afterFunction) function. It's not as elegant as the rest of automapper, but it might work.
CreateMap<User, UserViewModel>()
.ForMember(dest => dest.Notifications, map => map.MapFrom(src => src.UserNotification.Select(x => x.Notification)))
.AfterMap((src, dest) =>
{
foreach (var notificationVM in dest.Notifications)
{
notificationVM.HasRead = src.UserNotification.Where(x => x.NotificationId == notificationVM.Id).Select(x => x.HasRead).FirstOrDefault();
}
});

Retrieve multiple list from grandchild entity using lambda

I've three entities, say Parent, Child & GrandChild. This GrandChild has got three lists(a,b & c).
How to retrive all these lists using "Include" in Entity Framework?
I can retrive one list like this: Include("Parent.Child.GrandChild.a"),
but when I add another Include like : Include("Parent.Child.GrandChild.b"), it throws an error.
How will i retrive all these lists in a single query?
My code is as follows:
objUserNew = objContaxt.ContextRegistration
.Include("listing.postlist.commentslist")
.Include(‌​"listing.postlist.taglist")
.Include("listing.postlist.knocklist")
.FirstOrDefault(‌​x => x.id == objUser.id);
public class registration
{
public int id { get; set; }
public string firstname { get; set; }
public forgtPass forgtPass { get; set; }
public List<listing> listing { get; set; }
}
public class listing
{
public int id { get; set; }
public string address { get; set; }
public List<post> postlist { get; set; }
}
public class post
{
public int id { get; set; }
public string imgUrl { get; set; }
public List<tag> taglist { get; set; }
public List<comments> commentslist { get; set; }
public List<knoqs> knoqs { get; set; }
}
public class tag
{
public string name { get; set; }
}
public class comments
{
public int id { get; set; }
public string comment { get; set; }
public status status { get; set; }
}
public class knoqs
{
public int id { get; set; }
public virtual int registration_id { get; set; }
[ForeignKey("registration_id")] public registration registration { get; set; }
public status status { get; set; }
}

EntityFramework code first keys

I have following tables: User, UserGroups, and UserInGroups. You can see them on picture below. When i call User i want to be able to get Groups that user is in (UserInGroups). I am reading materials about EntityFramework but i am unable to make connections in code to to that, what am i missing? Do i need to connect them onModelCreating?
Currently i am not getting any data from UserInGroup or UserGroups.
DB looks like this
My classes look like this:
public class User : BaseEntity
{
public int RoleId { get; set; }
public Role Role { get; set; }
public UserGroup UserGroup { get; set; }
public UserInGroup UserInGroup { get; set; }
}
public class UserGroup : BaseEntity
{
public UserGroup()
{
Users = new List<User>();
UserInGroups = new List<UserInGroup>();
}
[StringLength(255)]
public string Name { get; set; }
public string KeyName { get; set; }
public List<User> Users { get; set; }
public List<UserInGroup> UserInGroups { get; set; }
}
public class UserInGroup : BaseEntity
{
public UserInGroup()
{
Users = new List<User>();
UserGroups = new List<UserGroup>();
}
public int UserId { get; set; }
public User User { get; set; }
public int UserGroupId { get; set; }
public UserGroup UserGroup { get; set; }
public List<User> Users { get; set; }
public List<UserGroup> UserGroups { get; set; }
}
DbContext:
public DbSet<GlobalSettings> GlobalSettings { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UserGroup> UserGroups { get; set; }
public DbSet<UserInGroup> UsersInGroups { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<GlobalSettings>().Property(x => x.Key).HasColumnAnnotation("Index", new IndexAnnotation(new[] { new IndexAttribute("Index_VariablenName") { IsClustered = false, IsUnique = true } }));
}
public abstract partial class BaseEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
}
public class User : BaseEntity
{
public string Username { get; set; }
public string Title { get; set; }
public FirstName { get; set; }
public string LasName { get; set; }
public Genders Gender { get; set; }
public string Email { get; set; }
public int RoleId { get; set; }
public string TechUser { get; set; }
public DateTime TechChangeDate { get; set; }
public int TechVersion { get; set; }
public bool IsDeleted { get; set; }
public virtual Role Role { get; set; }
public virtual ICollection<UserInGroup> UserInGroups { get; set; }
}
public class UserInGroup : BaseEntity
{
public int UserId { get; set; }
public int UserGroupId { get; set; }
public string TechUser { get; set; }
public DateTime TechChangeDate { get; set; }
public int TechVersion { get; set; }
public bool IsDeleted { get; set; }
public virtual User User { get; set; }
public virtual UserGroup UserGroup { get; set; }
}
public class UserGroup : BaseEntity
{
public string Name { get; set; }
public string KeyName { get; set; }
public string TechUser { get; set; }
public DateTime TechChangeDate { get; set; }
public int TechVersion { get; set; }
public bool IsDeleted { get; set; }
}
public class Role : BaseEntity
{
public string Name { get; set; }
}
public enum Genders
{
Male = 1,
Female = 2
}
You can use two methods to fill navigation properties. First is lazy-loading and second is explicit specifying of required properties.
For lazy-loading you should declare your navigation properties as virtual:
public class User : BaseEntity
{
public int RoleId { get; set; }
public virtual Role Role { get; set; }
public virtual UserGroup UserGroup { get; set; }
public virtual UserInGroup UserInGroup { get; set; }
}
public class UserGroup : BaseEntity
{
public UserGroup()
{
Users = new HashSet<User>(); // HashSet is more effective than List
UserInGroups = new HashSet<UserInGroup>();
}
[StringLength(255)]
public string Name { get; set; }
public string KeyName { get; set; }
public virtual ICollection<User> Users { get; set; } // ICollection is less restrective
public virtual ICollection<UserInGroup> UserInGroups { get; set; }
}
Now, you can load f.e. single user:
var justUser = dbContext.Users.Single(u => u.Id == 100);
When you need its properties they will by transparently loaded:
foreach (var userInGroup in user.UsersInGroups) // here is second loading
{
. . .
}
The second way is the calling of the Include method to explicit specifying required properties:
var userWithGroups = dbContext.Users
.Include(u => u.UserInGroups) // include single navigation property
.Include(ugs => ugs.Groups.Select(ug => ug.Group)) // include collection navigation property
.Single(u => u.Id == 100); // get the user with specified id and filled specified properties

Categories