I am trying to join two tables and getting an error I can't resolve.
var result = _context.FileModels
.Join(_context.FilesMetaData,
fm => fm.Id,
fmd => fmd,
(a, b) => new
{
fmId = a.Id,
fmds = b
});
return result;
This is the error message:
These are the models:
public class FilesMetaData
{
public Guid Id { get; set; }
public Guid FileId { get; set; }
public Guid ApplicationId { get; set; }
public string Comment { get; set; }
public string OtherData { get; set; }
public string AppUser { get; set; }
public string Origin { get; set; }
public string CreatedBy { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedAt { get; set; }
}
enter code here
and FileModels are some random columns that have one index.
Your join is missing a column:
.Join(_context.FilesMetaData,
fm => fm.Id,
fmd => fmd.FileModelId, // <--- Define the right column
You appear to have foreign keys but where are the navigation properties?
I would expect to see something like:
public class FilesMetaData
{
public Guid Id { get; set; }
public File File {get;set;} <-- Navigation Property
public Guid FileId { get; set; }
public Application Application {get;set;} <-- Navigation Property
public Guid ApplicationId { get; set; }
...
}
public class File
{
public Guid Id {get;set;}
...
}
public class Application
{
public Guid Id {get;set;}
...
}
This will automatically do the joins when required.
Related
Based on examples, I created the following custom join table (using EF Core 5), since I needed an extra property in my custom join table:
modelBuilder.Entity<Property>(property =>
{
property
.HasMany(_ => _.Addresses)
.WithMany(_ => _.Properties)
.UsingEntity<PropertyAddress>(
_ => _.HasOne(_ => _.Address).WithMany().HasForeignKey(_ => _.AddressId),
_ => _.HasOne(_ => _.Property).WithMany().HasForeignKey(_ => _.PropertyId));
});
public class PropertyAddress
{
public string PropertyId { get; set; }
public string AddressId { get; set; }
public int SequenceNumber { get; set; }
public Property Property { get; set; }
public Address Address { get; set; }
}
public class Property
{
public ICollection<Address> Addresses { get; set; }
}
public class Address
{
public ICollection<Property> Properties { get; set; }
}
The custom join table PropertyAddress is working as expected, however: How can I (programmatically) set the values for the custom property PropertyAddress.SequenceNumber before saving/updating records? (Because the whole joining mechanism is (now) still being handled 'behind the scene' by EF Core.)
1-First, you should have public DbSet PropertyAddress{ get; set; }
in your DBContext ,then use it to insert your object.
example:
1-Entity
public class GroupMember
{
public int GroupMemberId { get; set; }
[Required]
public int UserId { get; set; }
[Required]
public int GroupId { get; set; }
[Required]
public DateTime JoinDate { get; set; }
[Required]
public int RoleTypeGroupId { get; set; }
//Navigation
public User User { get; set; }
public Group Group { get; set; }
public RoleTypeGroup RoleType { get; set; }
}
2-DbContext
public class AppDataContext : DbContext
{
//Code
public DbSet<GroupMember> GroupMembers { get; set; }
}
3-you need create object of PropertyAddress and set his value as you want.
4- use EF to insert the object or update it
unitOfWork.GroupMemberRepository.Add(groupMember);
unitOfWork.SaveChanges();
I have two tables from which I want to fetch the data and return it to the API for consumable purposes. There is a relationship between the two tables.
[![enter image description here][1]][1]
When I try to fetch the data, it is returning only one row which is not what I want.
How can I return all the data related to ResellerId (8435 examples)?
This is my code:
public RateSheetModel GetRateSheet(int resellerId)
{
// This only returns only one row.
// How can I get all rows for all the same Id?
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
where r.ResellerId == resellerId
select r).First();
}
Models
public class WholesaleRateSheetMarkup
{
[Key]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
[StringLength(50)]
public string RatesheetName { get; set; }
}
public class WholesaleRateSheet
{
[Key]
public int RateSheetId { get; set; }
[Required]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
public decimal Peak { get; set; }
public bool IsSouthAfricanRate { get; set; }
public bool IsInertnationRate { get; set; }
public bool IsSpecificRate { get; set; }
public int DestinationGroupSetId { get; set; }
public int DestinationGroupId { get; set; }
public string DestinationLookup { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public DateTime LastUpdatedDate { get; set; }
public string UpdatedByUsername { get; set; }
}
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
join rateSheet in _Context.<tableName> on r.ResellerId equals rateSheet.ResellerId
where r.ResellerId == resellerId
select new { foo });
You're making a new type by doing this, as a combination of data from both tables. You can either define a model class and use something like
select new MyClass {
Foo = r.RateSheetMarkupId,
Bar = rateSheet.RateSheetName
}
Otherwise, no class definition is required. Simply using 'new' without a class will create an anonymous type with properties that match what you're selecting. The example here could be more precise if you share the entity names.
Altogether, going off your code:
public List<RateSheetModel> GetRateSheet(int resellerId)
{
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
join m in _Context.RateSheetMarkup on r.ResellerId equals m.ResellerId
where r.ResellerId == resellerId
select new RateSheetModel {
ResellerId = r.ResellerId
RatesheetName = m.RatesheetName
};
return rateSheetDetails.ToList<RateSheetModel>;
}
public RateSheetModel { //dunno what this model looks like, but example
public int ResellerId {get; set;}
public string RatesheetName {get; set;}
}
I want to list the data of the table sale, accessing the name of the user with the foreign key userId, what is the correct way to do this with the context?
using (var context = new AppDbContext())
{
var comic = context.sale.Select(d => d);
}
public class sale
{
public int saleId { get; set; }
public DateTime date { get; set; }
public int userId { get; set; }
}
public class user
{
public int userId { get; set; }
public string name { get; set; }
public string surname { get; set; }
public string email { get; set; }
public string password { get; set; }
}
Context:
modelBuilder.Entity<sale>()
.HasOne<user>()
.WithMany()
.HasForeignKey(p => p.userId);
You need to alter you classes to add navigation properties:
public class sale
{
public int saleId { get; set; }
public DateTime date { get; set; }
public int userId { get; set; }
public user user { get; set; }
}
public class user
{
public int userId { get; set; }
public string name { get; set; }
public string surname { get; set; }
public string email { get; set; }
public string password { get; set; }
public ICollection<sale> sales { get; set; } = new HashSet<sale>();
};
Then change your context:
modelBuilder.Entity<sale>()
.HasOne(a => a.user)
.WithMany(a => a.sales)
.HasForeignKey(p => p.userId);
You can then get the related data with:
var user = context.sale.Include(a => a.user)...
I've been for a while trying to find out why the Include clause is not loading the related collection: I have two classes with a one-to-many relationship:
public class AgencyNote : IAutId
{
[Key]
public int aut_id { get; set; }
public string Comment { get; set; }
[DisplayName("Note Created Date")]
public DateTime NoteDate { get; set; }
[DisplayName("Contact Date")]
public DateTime ContactDate { get; set; }
[ForeignKey("tbl_agency")]
public int AgencyId { get; set; }
[DisplayName("User")]
public string RipsUser { get; set; }
public virtual ICollection<AgencyNoteAttachment> AgencyNoteAttachments { get; set; }
public virtual tbl_agency tbl_agency { get; set; }
}
and
public class AgencyNoteAttachment
{
[Key]
public int aut_id { get; set; }
public string Url { get; set; }
public string FileName { get; set; }
public int AgencyNoteId { get; set; }
[NotMapped]
[ForeignKey("AgencyNoteId")]
public virtual AgencyNote AgencyNote { get; set; }
}
Context class:
public DbSet<AgencyNote> AgencyNotes { get; set; }
public DbSet<AgencyNoteAttachment> AgencyNoteAttachments { get; set; }
This is the action where I'm using the Include clause:
private IQueryable<AgencyNote> GetNotes(int agencyId)
{
return _ctx.AgencyNotes
.Include(a => a.tbl_agency)
.Include(a => a.AgencyNoteAttachments)
.OrderByDescending(f => f.NoteDate)
.Where(x => x.AgencyId == agencyId);
}
I'm getting AgencyNotesAttachments always null from this action even if I know it's not null, what's going on? Any question let me know...
If you add just the navigation properties between the related entities, then EF will create the FK column for you in the AgencyNoteAttachment table. Now, EF by convention can interpret AgencyNoteId is the FK of that relationship, but is good idea do that explicitly as you already have in your model or using ForeignKey attribute on FK property:
public class AgencyNoteAttachment
{
[Key]
public int aut_id { get; set; }
public string Url { get; set; }
public string FileName { get; set; }
[ForeignKey("AgencyNote")]
public int AgencyNoteId { get; set; }
public virtual AgencyNote AgencyNote { get; set; }
}
If you want to learn more about conventions, take a look this link
I hope this isn't a duplicate as I have been looking but I was looking more at the reasoning behind this.
I have set up a user object.
public class User
{
public User()
{
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public Guid UserGuid { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public int CompanyID { get; set; }
public int StatusID { get; set; }
[ForeignKey("StatusID")]
public Status Status { get; set; }
public int RoleID { get; set; }
[ForeignKey("RoleID")]
public UserRole UserRole { get; set; }
}
And the Child Objects
public class UserRole
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int RoleId { get; set; }
public string Role { get; set; }
}
public class Status
{
[Key]
public int StatusId { get; set; }
public string Description { get; set; }
}
When I call
var testuser = dbContext.User.Where(u => u.CompanyID == 1).FirstOrDefault();
I get users.Status as being null, but users.StatusID = 1.
however, if I call
var status = dbContext.Status.ToList();
var role = dbContext.UserRole.ToList();
var testuser = dbContext.User.Where(u => u.CompanyID == 1).FirstOrDefault();
then call testuser.Status, I can see the correct object related to StatusId of 1.
Can someone explain why this would solve the issue and also how I can make it work without having to call the following beforehand.
var status = dbContext.Status.ToList();
Thanks
You can try as shown below.
Note : Use Eager loading with Include()
Eager loading is the process whereby a query for one type of entity
also loads related entities as part of the query
using System.Data.Entity;
var testuser = dbContext.User.Where(u => u.CompanyID == 1)
.Include(p => p.Status)
.FirstOrDefault();
Just use your property like this. Keyword virtual put its property to lazy loading and then you can access the whole object.
public virtual Status Status { get; set; }
And BTW, I edited your class. There are un-needed things, because you can access StatusID by property Status (like int statID = Status.StatusID;) and same to UserRole.
public class User
{
public User()
{
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public Guid UserGuid { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public int CompanyID { get; set; }
public virtual Status Status { get; set; }
public virtual UserRole UserRole { get; set; }
}
}