I created an example rest webservice using WebApi.
Here is the controller class named Employee Controller.
namespace HelloWebApi.Controllers
{
public class EmployeesController : ApiController
{
private static IList<Employee> list = new List<Employee>()
{
new Employee()
{
Id = 12345, FirstName = "John", LastName = "Human",Department = 2
},
new Employee()
{
Id = 12346, FirstName = "Jane", LastName = "Public",Department = 3
},
new Employee()
{
Id = 12347, FirstName = "Joseph", LastName = "Law",Department = 2
}
};
// GET api/employees
public IEnumerable<Employee> Get()
{
return list;
}
// GET api/employees/12345
public Employee Get(int id)
{
return list.First(e => e.Id == id);
}
// POST api/employees
public void Post(Employee employee)
{
int maxId = list.Max(e => e.Id);
employee.Id = maxId + 1;
list.Add(employee);
}
// PUT api/employees/12345
public void Put(int id, Employee employee)
{
int index = list.ToList().FindIndex(e => e.Id == id);
list[index] = employee;
}
// DELETE api/employees/12345
public void Delete(int id)
{
Employee employee = Get(id);
list.Remove(employee);
}
public HttpResponseMessage Patch(int id, Delta<Employee> deltaEmployee)
{
var employee = list.FirstOrDefault(e => e.Id == id);
if (employee == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
deltaEmployee.Patch(employee);
return Request.CreateResponse(HttpStatusCode.NoContent);
}
}
}
Here I used all HTTP verbs method for insert, update, delete. I used a list that stores the Employee objects. insertion, deletion and updation are based on this list. But this program has no database connection. I want to know how to use Database access in this program. I would like to use tables from a database. How could i do it? Any useful link please.
Related
After migrating from .NET Core 2.x to .NET Core 5.0, we are facing this problem.
Error: (Added as a CODE for better readability)
The LINQ expression 'OUTER APPLY Projection Mapping:
(
SELECT e0.Id, e0.FirstName, e0.MiddleName, e0.LastName
FROM Employees AS e0
WHERE (((e0.Status != 4) && EXISTS (
Projection Mapping:
SELECT 1
FROM FunctionRoles AS f0
WHERE t.Id == f0.SchoolId)) && (e0.FunctionRoleId == (Projection Mapping:
EmptyProjectionMember -> 0
SELECT TOP(1) f1.Id
FROM FunctionRoles AS f1
WHERE (t.Id == f1.SchoolId) && (f1.Name == 'Manager')))) && (t.Id == e0.SchoolId)
) AS t0' could not be translated. Either rewrite the query in a form that can be translated,
or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
The code part:
using (var dbContext = _contextProvider.CreateContext())
{
var school = dbContext.Set<Domain.Model.School>()
.Where(s => s.Id == schoolId)
.Select(s => new SchoolSummaryDto
{
//... Some other properties
DocumentTemplates = s.DocumentTemplates != null ? s.DocumentTemplates.Select(a => new DocumentTemplateDto
{ Id = a.Id, Description = a.Description, SchoolId = a.SchoolId, FileName = a.FileName, DocumentTemplateTypeId = a.DocumentTemplateTypeId }).ToList() : new List<DocumentTemplateDto>(),
// This below chunk is causing problem.
Signers = s.Employees != null ? s.Employees.AsEnumerable().Where(
e => e.Status != PersistentStatusEnum.Removed &&
e.FunctionRoleId == s.FunctionRoles.AsEnumerable().Single(
b => b.Name == FunctionRolesEnum.Manager.ToString()).Id).AsEnumerable().Select(
a => new NameValueType { Id = a.Id, Name = string.Format("{0} {1} {2}", a.FirstName, a.MiddleName, a.LastName) }).ToList() : new List<NameValueType>(),
// .. Error chunk ends here
ContactPerson = s.ContactPerson,
Email = s.Email,
PhoneNumber = s.PhoneNumber,
SchoolId = s.Id,
SchoolName = s.Name,
Website = s.Website,
IsEnabled = s.IsEnabled,
IsRegistered = s.IsRegistered
}).FirstOrDefault();
}
What I tried:
As per these Microsoft links, Breaking Changes and Queryable projection not supported, I tried and applied changes AsEnumerable() accordingly as you can see above.
What changes are required now?
Libraries and Enviornment:
Database => MySql
Library => Pomelo.EntityFrameworkCore.MySql (5.0.0-alpha.2) Nuget Link
I sense either this MySql library is causing issue or EF Core 5 breaking changes.
Edit 1:
public class FunctionRole:AuditableEntity
{
public string Name { get; set; }
public string Description { get; set; }
public Guid SchoolId { get; set; }
public virtual School School { get; set; }
}
public class School:AuditableEntity
{
public bool IsRegistered { get; set; }
public bool IsEnabled { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string PhoneNumber { get; set; }
public string ContactPerson { get; set; }
public string ActivationCode { get; set; }
public virtual ICollection<FunctionRole> FunctionRoles { get; set; }
public virtual ICollection<DocumentTemplate> DocumentTemplates { get; set; }
}
I think it works with EF 2.x, because it silently evaluates this query on the client side.
Consider to rewrite query:
var query =
from s in dbContext.Set<Domain.Model.School>()
where s.Id == schoolId
from r in s.FunctionRoles
.Where(b => b.Name == FunctionRolesEnum.Manager.ToString())
.Take(1).DefaultIfEmpty()
select new SchoolSummaryDto
{
//... Some other properties
DocumentTemplates = s.DocumentTemplates
.Select(a => new DocumentTemplateDto
{
Id = a.Id,
Description = a.Description,
SchoolId = a.SchoolId,
FileName = a.FileName,
DocumentTemplateTypeId = a.DocumentTemplateTypeId
})
.ToList(),
Signers = s.Employees
.Where(e => e.Status != PersistentStatusEnum.Removed
&& e.FunctionRoleId == r.Id)
.Select(a => new NameValueType
{
Id = a.Id,
Name = a.FirstName + " " + a.MiddleName + " " + a.LastName
})
.ToList(),
ContactPerson = s.ContactPerson,
Email = s.Email,
PhoneNumber = s.PhoneNumber,
SchoolId = s.Id,
SchoolName = s.Name,
Website = s.Website,
IsEnabled = s.IsEnabled,
IsRegistered = s.IsRegistered
};
var school = query.FirstOrDefault();
You don't have to check for nulls, AsEnumerable is not needed, string.Format can be not translatable to the SQL.
Afternoon,
I would like to know how i would do this query in LINQ, can anyone please provide a hand.
SELECT Id, ExportDate,
(SELECT TOP (1) Id
FROM Orders
WHERE (PickupListId = PickingLists.Id)) AS StartOrderId,
(SELECT TOP (1) Id
FROM Orders AS Orders_1
WHERE (PickupListId = PickingLists.Id)
ORDER BY Id DESC) AS EndOrderId,
(SELECT COUNT(Id) AS Expr1
FROM Orders AS Orders_2
WHERE (PickupListId = PickingLists.Id)) AS NumberOfOrders
FROM PickingLists
ORDER BY ExportDate DESC
Update
I have updated my code as per Andrei's solution, however there is an issue converting the ID's please can you see what it could be?
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<GetPickingLists> GetPickingLists()
{
using (aboDataDataContext dc = new aboDataDataContext())
{
var query = from list in dc.pickingLists
orderby list.ExportDate descending
select new GetPickingLists
{
plId = list.Id,
plDate = list.ExportDate,
orderStart = Convert.ToInt32(dc.amzOrders.Where(order => order.pickupListId == list.Id).FirstOrDefault()),
orderEnd = Convert.ToInt32(dc.amzOrders.Where(order => order.pickupListId == list.Id).OrderByDescending(order => order.id).FirstOrDefault()),
orderCount = dc.amzOrders.Where(order => order.pickupListId == list.Id).Count(),
};
return query.ToList();
}
}
I have created this to set up the response, not sure if this is needed. Cheers.
public class GetPickingLists
{
public int plId { get; set; }
public int orderStart { get; set; }
public int orderEnd { get; set; }
public int orderCount { get; set; }
public DateTime plDate { get; set; }
}
var query = from list in dbContext.PickingLists
orderby list.ExportDate descending
select new
{
list.Id,
list.ExportDate,
StartOrderId = dbContext.Orders.Where(order => order.PickupListId == list.Id).FirstOrDefault().Id,
EndOrderId = dbContext.Orders.Where(order => order.PickupListId == list.Id).OrderByDescending(order => order.Id).FirstOrDefault().Id,
NumberOfOrders = dbContext.Orders.Where(order => order.PickupListId == list.Id).Count(),
}
Try it like this:
var query = db.PickingLists
.OrderByDescending(pl => pl.ExportDate)
.Select(pl => new GetPickingLists {
plId = pl.Id,
plDate = pl.ExportDate,
orderStart = db.Orders.FirstOrDefault(o => o.PickupListId = pl.Id).Id,
orderEnd = db.Orders.LastOrDefault(o => o.PickupListId = pl.Id).Id,
orderCount= db.Orders.Count(o => o.PickupListId = pl.Id)
});
Assume that I have a very simple db diagram:
and a view for it:
create view vTraining
as
select t.Id as TrainingId,t.[Status] ,
t.[User], t.Title,t.Organisation,t.[Month],t.[Year],
s.Id as SubjectId, s.Name as SubjectName,
c.Text as Comment
from Training t
join Subject s on s.Training = t.Id
join Comment c on c.Training = t.Id
with sample data:
As you can see, this is a single training with three subjects.
I want to map this result to this structure by linq to sql:
public class ViewModel
{
public string Comment { set; get; }
public List<Item> Trainings { set; get; }
}
public class Item
{
public int TrainingId { set; get; }
public int User { set; get; }
public int Status { set; get; }
public string Title { set; get; }
public string Organisation { set; get; }
public int? Month { set; get; }
public int Year { set; get; }
public List<KeyValuePair<int, string>> Subjects { set; get; }
}
This is my query, that I created:
var data = (from training in dc.vTrainings
group training by new
{
training.TrainingId,
training.Status,
training.Month,
training.Organisation,
training.Title
}
into g
select new ViewModel()
{
Comment = g.Select(x =>
x.Comment).First(),
Trainings = g.Select(
x => new Item()
{
Month = x.Month,
Organisation = x.Organisation,
Title = x.Title,
Year = x.Year,
Subjects = g.Select(
z => new KeyValuePair<int, string>(z.SubjectId, z.SubjectName)).ToList()
}).ToList()
})//.GroupBy(x => x.Trainings).Select(x => x.Key)
.ToList();
Unfortunatelly the result I get is not the one I want:
The ViewModel object is created only ones what is ok, but for each single subject, the new Item is created (should be one). The Subjets list is created correctly. I tried to create a second group by, and some other things, but this is the best result I can get for now.
How to write this query to get one ViewModel object which has one Item object with three subjects?
I finally got my the proper result:
var data = (from g in
(from training in dc.vTrainings
where training.Status ==1
group training
by new
{
training.TrainingId,
training.Status,
training.Month,
training.Organisation,
training.Title
}
into g
select g).AsEnumerable()
select new ViewModel()
{
Comment = g.Select(x =>
x.Comment).FirstOrDefault(),
Trainings = g.GroupBy(x => x.Status).Select(
x => new Item()
{
Month = g.Key.Month,
Organisation = g.Key.Organisation,
Title = g.Key.Title,
Subjects = (from i in g select new KeyValuePair<int, string>(i.SubjectId, i.SubjectName)).ToList()
}).ToList()
}).ToList();
This query works only for one training, but for me this is not a problem, because I filtering it by the newest status. Still I'm curious how to write it for more than one training.
Try this:
var trainings =
dc.vTrainings
.GroupBy(
t => new
{
t.TrainingId,
t.Status,
t.Month,
t.Organisation,
t.Title,
t.User,
t.Year
},
t =>
new
{
t.SubjectId,
t.SubjectName
})
.ToList()
.Select(
t =>
new Item
{
TrainingId = t.Key.TrainingId,
Status = t.Key.Status,
Month = t.Key.Month,
Organisation = t.Key.Organisation,
Title = t.Key.Title,
User = t.Key.User,
Year = t.Key.Year,
Subjects =
t.Select(s => new KeyValuePair<int,string>(s.SubjectId,s.SubjectName)).ToList()
});
Below is my code using LINQ to SQL,on execution I get an error msg saying "Object reference not set to an instance of an object".I've joined 3 tables Users,UsersinRoles and Roles.Userinroles is the bridge table.I use join to retrive datas from 2 tables using bridge table i get the Object reference error.
public class Users : CollectionFactoryBase
{
public Users()
{
this.Summary = "Collection of Users";
}
public override Collection MakeCollection(CollectionRequestContext context)
{
UsersDataContext m_dataContext = new UsersDataContext();
const int maxItems_c = 150;
try
{
// string sessionvalue = HttpContext.Current.Session["SessionKey"] as string;
var Users = from p in m_dataContext.aspnet_Users
join t in m_dataContext.aspnet_UsersInRoles on
p.UserId equals t.UserId
join r in m_dataContext.aspnet_Roles on
t.RoleId equals r.RoleId
select new
{
UserName = p.UserName,
UserId = p.UserId,
RoleId = r.RoleId,
RoleName = r.RoleName,
userid = t.UserId,
roleid = t.RoleId
};
Collection collection = new Collection();
collection.Name = "Users";
foreach (var user in Users.Take(maxItems_c) )
{
collection.AddItem(user.UserName, user.RoleName, null, null, null, null, null);
}
return collection;
}
catch (Exception ex)
{
return ErrorCollection.FromException(ex);
}
}
}
}
Don't you think that last statement should be first one?
I'm trying to write a linq to sql method that handles sorting, paging, and filtering for an ajax grid. I created a partial class Employee that has a TotalRecordCount, as I need to pass this to the javascript for setting up the pager. The problem is that it won't build because I can't set the AnonymousType#1.TotalRecordCount, it's read-only. Yet if I do "select new Employee", then it will throw the Exception - "Explicit construction of entity type 'InVision.Data.Employee' in query is not allowed.".
Here's the code...
public string GetPageJSON(string sortColumn, string sortDirection, int pageNumber, int pageSize, EmployeeSearch search)
{
var query = from e in db.Employees
select new
{
EmployeeID = e.EmployeeID,
FirstName = e.FirstName,
LastName = e.LastName,
LoginName = e.LoginName,
IsLockedOut = e.IsLockedOut,
TotalRecordCount = e.TotalRecordCount
};
//searching.
if (search.FirstName.Length > 0) query = query.Where(e => e.FirstName.Contains(search.FirstName));
if (search.LastName.Length > 0) query = query.Where(e => e.LastName.Contains(search.LastName));
if (search.LoginName.Length > 0) query = query.Where(e => e.LoginName.Contains(search.LoginName));
if (search.Status.Length > 0) query = query.Where(e => (search.Status == "Active" && !e.IsLockedOut)
|| (search.Status == "Inactive" && e.IsLockedOut));
//sorting.
query = query.OrderBy(sortColumn, sortDirection);
//get total record count.
int totalRecordCount = query.Count();
//paging.
query = query.Skip((pageNumber - 1) * pageSize).Take(pageSize);
//set total record count.
var list = query.ToList();
if (list.Count > 0)
{
list[0].TotalRecordCount = totalRecordCount; //throws exception
}
//return json.
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}
You'll want to select the original objects rather than mapping them to new objects (whether of the same type, or an anonymous type).
Replace this:
var query = from e in db.Employees
select new
{
EmployeeID = e.EmployeeID,
FirstName = e.FirstName,
LastName = e.LastName,
LoginName = e.LoginName,
IsLockedOut = e.IsLockedOut,
TotalRecordCount = e.TotalRecordCount
};
With this:
var query = db.Employees.AsQueryable();
Then later on replace this:
var list = query.ToList();
if (list.Count > 0)
{
list[0].TotalRecordCount = totalRecordCount;
}
With this:
var list = from e in query
select new
{
EmployeeID = e.EmployeeID,
FirstName = e.FirstName,
LastName = e.LastName,
LoginName = e.LoginName,
IsActive = !e.IsLockedOut,
TotalRecordCount = totalRecordCount
};
I think that should be everything. If the JavaScriptSerializer requires a List, just make sure you use it like this: return serializer.Serialize(list.ToList());
I ended up using a custom view class to get this to work...
partial class EmployeeView
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string LoginName { get; set; }
public bool IsActive { get; set; }
public int TotalRecordCount { get; set; }
}
public string GetPageJSON(string sortColumn, string sortDirection, int pageNumber, int pageSize, EmployeeSearch search)
{
var query = from e in db.Employees
select new EmployeeView
{
EmployeeID = e.EmployeeID,
FirstName = e.FirstName,
LastName = e.LastName,
LoginName = e.LoginName,
IsActive = !e.IsLockedOut,
TotalRecordCount = 0
};
//searching.
if (search.FirstName.Length > 0) query = query.Where(e => e.FirstName.Contains(search.FirstName));
if (search.LastName.Length > 0) query = query.Where(e => e.LastName.Contains(search.LastName));
if (search.LoginName.Length > 0) query = query.Where(e => e.LoginName.Contains(search.LoginName));
if (search.Status.Length > 0) query = query.Where(e => (search.Status == "Active" && e.IsActive)
|| (search.Status == "Inactive" && !e.IsActive));
//sorting.
query = query.OrderBy(sortColumn, sortDirection);
//get total record count.
int totalRecordCount = query.Count();
//paging.
query = query.Skip((pageNumber - 1) * pageSize).Take(pageSize);
//set total record count.
var list = query.ToList();
if (list.Count > 0)
{
list[0].TotalRecordCount = totalRecordCount;
}
//return json.
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}