include field from another class - entity-framework

I have a class called Program that has a field called ProgramStatusCode. I'm planning to create another class called Status that has the StatusCode (ID) and StatusDescription. The Status class has a column called StatusType that needs to be filtered on Program and an Active column that needs to be filtered on Yes.
How do I add StatusDescription to the Program class that's already filtered on Program and Yes?
Here are the classes:
Program.cs
public class Program
{
public decimal ID { get; set; }
public string ProgramName { get; set; }
public string ProgramDescription { get; set; }
public string ProgramStatusCode { get; set; }
}
Status.cs
public class Status
{
public int ID { get; set; }
public string StatusType { get; set; }
public string StatusDescription { get; set; }
public string Active { get; set; }
}
Update
The work around that I'm doing is creating another class called ProgramFinal with a field called Status. Instead of creating another class just to include Status, I'd like to have Status in the Program class.
Here is the code:
ProgramFinal.cs
public class ProgramFinal
{
public decimal ID { get; set; }
public string ProgramName { get; set; }
public string ProgramDescription { get; set; }
public string Status { get; set; }
}
Linq Query:
programFinal = (from program in dbContext.Program
join status in dbContext.Status on program.ProgramStatusCode equals status.ID
where status.Active.Contains("Y") && status.StatusType.Contains("Program") && program.ProgramName.Contains(programName)
select new ProgramFinal
{
ID = program.ID,
ProgramName = program.ProgramName,
ProgramDescription = program.ProgramDescription,
Status = status.StatusDescription
}).FirstOrDefault();
So instead of creating a new class just to get the Status Description, I'd like to have Status Description in the Program class itself.
Thanks!

Related

Getting value of Navigation property in join

I have generated the classes from the database using scaffold.
public partial class Class1
{
public int ID { get; set; }
public int Class2ID { get; set; }
public string Name { get; set; }
public DateTime Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public virtual Class2 Class2 { get; set; }
}
public partial class Class2
{
public Class2()
{
Class1 = new HashSet<Class1>();
}
public int ID { get; set; }
public string Allotment { get; set; }
public string Manual { get; set; }
public virtual ICollection<Class1>Class1 {get; set;}
}
So there is a requirement to join these two tables in entity and get the data. And I am getting the result.
Here is my code:
var _class1Repo = UnitWork.GetGenericRepositoryFor<Class1>().AsNoTracking();
var _class2Repo = UnitWork.GetGenericRepositoryFor<Class2>().AsNoTracking();
var query = from _cls1 in _class1 in _class1Repo
join _cls2 in _class2Repo on _cls1.Class2ID = _cls2.ID
where _cls2.ID = 2
select new Class1() {
Name =_cls1 .Name,
Address =_cls1.Address,
City =_cls1 .City,
Country =_cls1.Country
// I want just only one property value inside this from class2
};
I need to include Class2 one property. How can I do that? Is there a way to achieve this?
Define your Class1.cs like this:
public class Class1
{
public int ID { get; set; }
public int Class2ID { get; set; }
public string Name { get; set; }
public DateTime Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public virtual Class2 Class2 { get; set; }
public Class1() {}
// Define this constructor
}
A constructor is a special method of the class which gets automatically invoked whenever an instance of the class is created.
So whenever you created instance you can easy to access the property.

LINQ query throw exception on FirstOrDefault method

I'm using EF core, and I have a many-to-many relationship between two entity
IotaProject <--> User
Here's entities & dto related to the question
public class IotaProject
{
[Key]
public int Id { get; set; }
[Required]
public string ProjectName { get; set; }
[Required]
public DateTime Create { get; set; }
public ICollection<ProjectOwnerJoint> Owners { get; set; } = new List<ProjectOwnerJoint>();
}
public class ProjectOwnerJoint
{
public int IotaProjectId { get; set; }
public IotaProject IotaProject { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class User
{
[Key]
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string ShortName { get; set; }
[Required]
public string Email { get; set; }
public ICollection<ProjectOwnerJoint> OwnedProjects { get; set; } = new List<ProjectOwnerJoint>();
}
public class ApplicationDbContext : DbContext
{
public DbSet<IotaProject> IotaProjects { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<ProjectOwnerJoint> ProjectOwnerJoint { get; set; }
}
public class IotaProjectDisplayDto
{
public int Id { get; set; }
public string ProjectName { get; set; }
public DateTime Create { get; set; }
public UserMinDto Owner { get; set; }
public int Count { get; set; }
public IEnumerable<UserMinDto> Reviewers { get; set; }
}
public class UserMinDto
{
public int Id { get; set; }
public string FullName { get; set; }
public string ShortName { get; set; }
}
Following LINQ is the problem, the LINQ purpose is to convert IotaProject to IotaProjectDisplayDto, and key part is that Owners property of IotaProject is ICollection and Owner property in IotaProjectDisplayDto is just one single element UserMinDto, so I only need to get the first element of IotaProject's Owners and that's FirstOrDefault() comes.
IEnumerable<IotaProjectDisplayDto> results = _db.IotaProjects.Select(x => new IotaProjectDisplayDto
{
Id = x.Id,
ProjectName = x.ProjectName,
Create = x.Create,
Owner = x.Owners.Select(y => y.User).Select(z => new UserMinDto { Id = z.Id, FullName = z.FullName, ShortName = z.ShortName }).FirstOrDefault()
});
return results;
it throws run-time exception
Expression of type 'System.Collections.Generic.List`1[ToolHub.Shared.iota.UserMinDto]' cannot be used for parameter
of type 'System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto]'
of method 'ToolHub.Shared.iota.UserMinDto FirstOrDefault[UserMinDto](System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto])' (Parameter 'arg0')
I'm guessing it's probably related to deferred execution, but after read some posts, I still can't resolve it.
Any tips would be appreciated.
Right now, the only way I can get this work is I change type of Owner property in IotaProjectDisplayDto into IEnumrable, which will no longer need FirstOrDefault() to immediate execution. And later on, I manually get the first element in the client to display.
This issue happened in Microsoft.EntityFrameworkCore.SqlServer 3.0.0-preview7.19362.6
I end up downgrade to EF core stable 2.2.6 as Ivan suggested in comment, and everything works fine.

how to Pull data with paramter using Azure Offline Sync?

I have schema as below and I would like to know if I can get all the TaskCategoryMappings by CategoryId when I have to pulll all data. I went through the documentation here but I cant figure out how to do it ? All the examples are like this one based on UserId. but userid is used for also authentication and on the server side I already handle it fine to return only mappings belong to relevant user and i want in adition to filter by CategoryId?
another SO sample is here also using userId Parameter Passing with Azure Get Service
public class TaskCategoryMapping : TableData
{
public string TaskId { get; set; }
public string CategoryId { get; set; }
public string UserId { get; set; }
}
According to your description, I checked this issue on my side and found that it could work as expected, you could follow the details below to check your code:
Backend models:
public class Tag : EntityData
{
public string TagName { get; set; }
public bool Status { get; set; }
}
public class Message : EntityData
{
public string UserId { get; set; }
public string Text { get; set; }
public virtual Tag Tag { get; set; }
[ForeignKey("Tag")]
public string Tag_Id { get; set; }
}
GetAllMessage action:
// GET tables/Message
public IQueryable<Message> GetAllMessage()
{
return Query();
}
For the client, I just invoke the online table for retrieving the message entities as follows:
Model on client-side:
public class Message
{
public string Id { get; set; }
public string UserId { get; set; }
public string Text { get; set; }
public string Tag_Id { get; set; }
}
var result=await mobileServiceClient.GetTable<Message>().Where(msg => msg.Tag_Id == "c3cd4cf8-7af0-4267-817e-f84c6f0e1733").ToListAsync();
For offline table, the pull operation query would
await messageSyncTable.PullAsync($"messages_{userid}", messageSyncTable.Where(m => m.Tag_Id == "<Tag_Id>"));
Use fiddler, you could find that the request would look like this:
https://{your-app-name}.azurewebsites.net/tables/Message?$filter=Tag_Id eq 'c3cd4cf8-7af0-4267-817e-f84c6f0e1733'

I get UpdateException when i try to Update a collection property

I am in an MVC4 application and i am using EF CodeFirst.
When I try to run the following code:
public void Autorizare(int cerereId, Persoana persoana)
{
var cerere = _db.Cereri.Find(cerereId);
cerere.Autorizare.Add(persoana);
_db.SaveChanges();
}
I get an error like this:
Entities in 'CerereDbContext.Persoane' participate in the 'Actiune_Executanti' relationship. 0 related 'Actiune_Executanti_Source' were found. 1 'Actiune_Executanti_Source' is expected.
i have tried Entity(Actiune).State = EntityState.Modified, but no results.
I have a main POCO:
public class Cerere
{
public int Id { get; set; }
...
public virtual ICollection<Actiune> Actiuni { get; set; }
...
}
the Actiune class looks like this
public class Actiune
{
public int Id { get; set; }
public DateTime Data { get; set; }
public String Nume { get; set; }
public virtual ICollection<Persoana> Executanti { get; set; }
public String Stadiu { get; set; }
public String Obs { get; set; }
}
And Persoana:
public class Persoana
{
public int Id { get; set; }
public DateTime Data { get; set; }
public String Nume { get; set; }
}
From your model the Cerere does not have a property named Autorizare; however it does have one named Actiuni. Which is of type Actiune not Persoana which is what you are trying to add to it. Please post the rest of the Class Definition.

Entity framework foreign key

I have 2 classes
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
and
public class PersonWebsite
{
public int Id { get; set; }
public string Website { get; set; }
public int PersonId{ get; set; }
}
I've seen stuff like this being done before
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public ICollection<PersonWebsite> PersonWebsites{ get; set; }
}
How could I go about implementing the code that when a Person is initialized, the PersonWebsites List will automatically be initialised and get all the PersonWebsite objects that have the same PersonId as the class that calls it.
Lazy Loading:
You can make PersonWebsites property virtual:
public virtual ICollection<PersonWebsite> PersonWebsites{ get; set; }
Entity framework will load it from the database as soon as it's required.
Also this method requires you to have lazy loading enabled which is by default:
DbContext.ContextOptions.LazyLoadingEnabled = true;
Eager Loading:
You can use include to force entity framework to load PersonWebsites on the first query:
DbSet.Include(p => p.PersonWebsites);
You may also want to change your PersonWebsite class like this, in order to navigate to the person from the PersonWebsite object (using Lazy-Loading):
public class PersonWebsite
{
public int Id { get; set; }
public string Website { get; set; }
[ForeignKey("Person")]
public int PersonId{ get; set; }
public virtual Person Person {get;set;}
}