Good day, a really newbie developer here.
I Have a form and it have a entity of "QueueNumber" Can someone show me how to code so that when ever i save my form it generates automatically QueueNumber + the Prefix, btw my prefix entity is in another class
public class Queue
{
public int QueueId { get; set; }
[Required]
public string Name { get; set; }
public string QueueNumber
public int ServiceId { get; set; }
public Service Service { get; set; }
}
-
public class Service
{
public int ServiceId { get; set; }
[Display(Name = "Service Name")]
public string ServiceName { get; set; }
[Display(Name = "Service Letter")]
public string ServiceLetter { get; set; }
[Display(Name = "Status")]
public bool? Status { get; set; }
[Display(Name = "Assigned Location")]
public int? LocationId { get; set; }
public virtual Location Location { get; set; }
public virtual ICollection<Customer> Customer { get; set; }
}
Outcome in database :
1. A001
2. A002
3. A003
i just want to be able to generate a queue number automatically and when i save in data base its like A= Service Letter and 001=QueueNumber. Thankyou
If the QueueNumber needs to be persisted to the table, then I would set it up as a calculated column so that the database can manage computing it and updating it if the underlying fields change.
If it is just something that you want to represent in the UI then I would recommend having the view model calculate this.
The entity can calculate something like this with a [NotMapped] attribute. For example:
public class Queue
{
public int QueueId { get; set; }
[Required]
public string Name { get; set; }
[NotMapped]
public string QueueNumber
{
get { return string.Format("{0}{1:000}", Service?.ServiceLetter ?? "?", QueueId);
}
[ForeignKey("Service")]
public int ServiceId { get; set; }
public Service Service { get; set; }
}
The problem with this approach is that to be able to rely on your Queue to reveal a QueueNumber, the Queue must eager load the Service, or you enable lazy loading and risk that performance hit vs. having Service == #null and getting an exception or invalid QueueNumber result. In the above example, if the Service isn't eager loaded you will get back something like "?001".
I prefer to use ViewModels for a number of reasons including performance, security, and handling conditions like this more cleanly.
For example, given a QueueViewModel as such:
[Serializable]
public sealed class QueueViewModel
{
public int QueueId{ get; set; }
public string Name { get; set; }
public string ServiceName { get; set; }
public string ServiceLetter { get; set; }
public string QueueNumber
{
return string.Format("{0}{1:000}", ServiceLetter, QueueId);
}
}
Then when reading the data, we don't pass Entities to the view, we pass our view model...
var viewModel = context.Queues
.Where(x => x.QueueId == queueId)
.Select(x => new QueueViewModel
{
QueueId = x.QueueId,
Name = x.Name,
ServiceName = x.Service.Name,
ServiceLetter = x.Service.ServiceLetter
}).Single();
return viewModel;
The benefits of this approach:
We don't have to worry about eager/lazy loading. The query fetches everything needed, and our view model can compute anything needed from the data loaded. (Queries can compute values as well if you like, but be wary of limitations in that the query has to be able to go to SQL, so no user functions, etc.)
Performance is improved since the query only returns the data needed rather than entire entity graphs, and no rish of lazy load hits.
Security is improved, we expose no more data to the client than is expected/needed, and we don't open the door for "lazy" updates where entities are attached to a context and saved without proper validation.
Related
I would like to query a table, which holds workflow events with the appr. user id. And instead of the user id, I would like to show the user name.
I have this model:
public class WorkflowEvent
{
public long Id { get; set; }
public DateTime EventDate { get; set; }
public WorkflowStatus Status { get; set; }
public int UserId { get; set; }
public AppUser User { get; }
public string Note { get; set; }
public long WorkflowId { get; set; }
public long DocumentId { get; set; }
}
And this is the user model (it is the standard IdentityUser, I use Asp.Net Identity):
public class AppUser : IdentityUser<int>
{
public string RealName { get; set; }
public string AppTheme { get; set; }
}
And this is my query:
public IEnumerable<WorkflowEvent> WorkflowEvents(int DocumentId)
{
return DataContext.WorkflowEvents.Where(e => e.DocumentId == DocumentId).Include(e => e.User).OrderBy(e => e.EventDate);
}
Unfortunatelly, I get following error on this: System.InvalidOperationException: Lambda expression used inside Include is not valid. In the WorkflowEvents table, there is a foreign key on the UserId, of course.
Have you any idea, why do I get this error message? What goes wrong?
Both Sami's and Nik's suggestions helped. I added the setter to the AppUser. And then I got the error, that the AppUser object isn't exists. This due to the fact, that I have in my app two datacontexts: one for the domain models and one for Identity. So, I just add this line of code to the domain data context:
public DbSet<AppUser> AspNetUsers { get; set; }
And everything worked like a charm.
I am having a problem with primary key/Id of one table in a project.
In this table, the Id suddenly jumped from 38 to 1039.
Now the real issue is, when i find the entity by 1039 it doesn't exists but finding it by 39 gives me the entity.
I am not sure about this behaviour and hence not able to find the solution.
My model
public class Domain : Entity
{
public string Name { get; set; }
public string Description { get; set; }
}
public abstract class Entity
{
public int Id { get; set; }
public DateTime InsertDate { get; set; }
public DateTime? UpdateDate { get; set; }
public DateTime? DeleteDate { get; set; }
public bool IsDeleted { get; set; }
}
Method is like this...
public async Task<Response> Delete(int id)
{
var domain = await DataContext.Domains.FindAsync(id);
if (domain == null)
{
return new Response(ResponseType.NotFound);
}
}
Can anyone please help ?
it depend from Database setting IDENTITY-CACHE.
Identity cache store some values of a identity columns in case of SQL CRASH during a transaction or similar.
To avoid gaps in an identity column, you need to set IDENTITY-CACHE to OFF running this command on a SQL query window:
ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFF
GO
you will find more informations here:
https://social.technet.microsoft.com/wiki/contents/articles/40666.sql-server-2017-identity-cache-feature.aspx
I have an application, structured like this:
Application.Domain
Application.Web.Mvc
Application.MongoDb
In Application.Domain i keep all the POCOs of the application (the domain models).
public class Product
{
public string Id { get; set; }
public string ProductName { get; set; }
public DateTime CreatedDate { get; set; }
}
Now, because i am using MongoDb, i also need to use some of the [BsonAttribute], in order to customize the serialization process.
For example:
public class Product
{
[BsonId]
public string Id { get; set; }
public string ProductName { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local, DateOnly = true)]
public DateTime CreatedDate { get; set; }
}
If i add these attributes, i will need to also add a reference to MongoDB.Bson.Serialization.Attributes in the Application.Domain project, which i want to avoid.
I think the correct way to do this is to create mapping objects in the Application.MongoDb project, and always map them from POCO to MongoObjects and the other way around every time i work with MongoDb repos.
If this is the correct solution, isn't this a bit overkill?
I am new in ASP.NET MVC web development. I am just trying to overload a simple odata controller method for several days but failing again and again. I want to know the mystery behind this. Please help me...
This is my EducationInfo Model class...
public partial class EducationInfo
{
[Key]
public int EducationID { get; set; }
[ForeignKey("UserID")]
public int UserID { get; set; }
[Required]
public string Title { get; set; }
[Required]
[StringLength(50)]
public string EducationLevel { get; set; }
public string Department_Group { get; set; }
public string InstituteName { get; set; }
[Required]
public string Board_University_Name { get; set; }
[StringLength(30)]
public string Duration { get; set; }
public DateTime PassingYear { get; set; }
[StringLength(30)]
public string Result { get; set; }
public virtual UserInfo UserInfo { get; set; }
}
And here is one of my EducationInfoesController GET methods which accepts EducationID as parameter
// GET: odata/EducationInfoes(5)
[EnableQuery]
public SingleResult<EducationInfo> GetEducationInfo([FromODataUri] int key)
{
return SingleResult.Create(db.EducationInfoes.Where(educationInfo => educationInfo.EducationID == key));
}
I want to overload this method in a such way that it might take 2 parameters [e.g. GetEducationInfo(int UserID, string EducationLevel)] and return only a single result based on the combination of two parameters (UserID and EducationLevel).
I have already tried to overload this method by following code...
// GET: odata/EducationInfoes(5, "bachelor")
[EnableQuery]
public SingleResult<EducationInfo> GetEducationInfo([FromODataUri] int key, string eLevel)
{
return SingleResult.Create(db.EducationInfoes.Where(educationInfo => educationInfo.UserID == key && educationInfo.EducationLevel == eLevel));
}
But when I'm sending GET requst to my WebService by this URL http://localhost:10194/odata/EducationInfoes(5, "Bachelor"), I'm getting this message:
No HTTP resource was found that matches the request URI 'http://localhost:10194/odata/EducationInfoes(5,"Bachelor")'.
If I change the default method to the following...
// GET: odata/EducationInfoes(5)
[EnableQuery]
public SingleResult<EducationInfo> GetEducationInfo([FromODataUri] int key)
{
return SingleResult.Create(db.EducationInfoes.Where(educationInfo => educationInfo.UserId== key));
}
and requesting using this url http://localhost:10194/odata/EducationInfoes(3) and getting this message
The action 'GetEducationInfo' on controller 'EducationInfoes' returned a SingleResult containing more than one element. SingleResult must have zero or one elements.
this message is returned because every single user has multiple Educational Information stored in EducationInfo table.
But I must have to get every EducationInfo result separately or as single result based on UserID and EducationLevel but not based on EducationID. Please help me...
Background
Since I am new to using Entity Framework, I try to build something simple first. I started a post asking how I can store lists of objects in SQL Server:
Storing list of objects in SQL Server database with code-first
Now I have built up two models:
public class MultipleChoiceQuestion
{
[Key]
public Guid MultipleChoiceQuestionId { get; set; }
[Required]
public string Question { get; set; }
[Required]
public ICollection<PossibleChoice> PossibleChoices { get; set; }
}
public class PossibleChoice
{
[Key, Column(Order = 1), ForeignKey("MultipleChoiceQuestion")]
public Guid MultipleChoiceQuestionId { get; set; }
[Key, Column(Order = 2)]
public int ChoiceIndex { get; set; }
[Required]
public string AnswerText { get; set; }
public MultipleChoiceQuestion MultipleChoiceQuestion { get; set; }
}
In QuestionContext : DbContext I have defined:
public DbSet<MultipleChoiceQuestion> McQuestions { get; set; }
Besides, I have a controller with a Get() endpoint:
[RoutePrefix("api/McQuestion")]
public class McQuestionController : ApiController
{
[AllowAnonymous]
[Route("")]
public IEnumerable<MultipleChoiceQuestion> Get()
{
var context = new QuestionContext();
return context.McQuestions;
}
}
Question
When I issue a GET request, the following object is returned.
[
{
"MultipleChoiceQuestionId": "fcaf709e-2f7d-e411-80bb-002219ac77b7",
"Question": "Which integer is a prime number?",
"PossibleChoices": null
},
{
"MultipleChoiceQuestionId": "20159ee7-2f7d-e411-80bb-002219ac77b7",
"Question": "Who is the person invented light bulbs?",
"PossibleChoices": null
}
]
How can I include the collection PossibleChoices in the GET result?
use context.McQuestions.Include("PossibleChoices").ToList();
However, you need to learn doing things the right way, so it is better to consider this:
1- Use Fluent API to map your entity to your table, you can use some tools to auto generate your entities (POCO) classes if you have already a database, check "EF 6 Tools Designer" Or "EF Reverse POCO generator".
2- Return DTOs from your Web API instead of returning the entities directly, and to map between the entity and the DTO you can use AutoMapper.