My project involves creating a new hotel room and 2 tables in my database will update. My tables are called RoomType and RoomFacility.
I can successfully update RoomType, but when I try to update RoomFacility and use RoomTypeID to make a new room facility, it fails. I always get 1 for my RoomFacilityID.
How can I update data for both tables, roomType and RoomFacility?
This is the code for my service to update my database
public void UpdateFacilityInRooms(List<int> FacilityIDs, int RoomTypeID)
{
List<HotelRoomFacility> hotelRoomFacilities =
_HotelRoomFacilityRopository.AsQueryable()
.Where(f => f.RoomTypeID == RoomTypeID).ToList();
foreach (int newRoomFacility in FacilityIDs)
{
if (hotelRoomFacilities.Where(h => h.RoomFacilityID == newRoomFacility).Count() == 0)
{
HotelRoomFacility facility = new HotelRoomFacility
{
RoomFacilityID = newRoomFacility,
RoomTypeID = RoomTypeID
};
_HotelRoomFacilityRopository.Add(facility);
}
}
_HotelRoomFacilityRopository.CommitChanges();
}
public RoomType NewRoom(int HotelID,int? RoomTypeID,
string RoomTypeName, string RoomTypeDescription)
{
RoomType room = new RoomType();
room.HotelID = HotelID;
room.RoomTypeID = RoomTypeID ?? 0;
room.RoomtypeName = RoomTypeName;
room.RoomTypeDescripton = RoomTypeDescription;
_RoomTypeRepository.Add(room);
_RoomTypeRepository.CommitChanges();
return room;
}
public RoomType UpdateRoom(int RoomTypeID, string RoomTypeName, string RoomTypeDescription, List<int> RoomFacilityIDs)
{
RoomType roomType = (from rt in _RoomTypeRepository.AsQueryable().Include(r => r.HotelRoomFacilities)
where rt.RoomTypeID == RoomTypeID
select rt).FirstOrDefault();
if (roomType == null)
return null;
roomType.RoomTypeName = RoomTypeName;
roomType.RoomTypeDescripton = RoomTypeDescription;
//Add New Room facilities
List<HotelRoomFacility> hotelRoomFacilities = _HotelRoomFacilityRopository.AsQueryable().Where(f => f.RoomTypeID == RoomTypeID).ToList();
foreach (int newRoomFacilityID in RoomFacilityIDs)
{
if (roomType.HotelRoomFacilities.Where(h => h.RoomFacilityID == newRoomFacilityID).Count() == 0)
{
roomType.HotelRoomFacilities.Add(new HotelRoomFacility
{
RoomFacilityID = newRoomFacilityID
});
}
}
foreach (HotelRoomFacility roomFacility in hotelRoomFacilities)
{
if (RoomFacilityIDs.Contains(roomFacility.RoomFacilityID) == false)
_HotelRoomFacilityRopository.Delete(roomFacility);
}
_RoomTypeRepository.Attach(roomType);
_RoomTypeRepository.CommitChanges();
return roomType;
}
Related
I need to call a method FormatCourseTitle() from linq query but receive error message "Linq to Entity does not recognize the method FormatCourseTitle..." How to solve this problem?
public ActionResult Index()
{
var searchResults = (from a in db.Courses
join b in db.Summary on
new { subject = a.subject, catalog = a.catalog, coursetitle = FormatCourseTitle(a.coursetitle) } equals
new { subject = b.Subject, catalog = b.Catalogno, coursetitle = b.CourseTitle } into ab
from b in ab.DefaultIfEmpty()
where a.Active == true
select new JoinModel
{
Courses = a,
Summary2020 = b
} ).ToList();
return View(searResults);
}
public class JoinModel
{
[Key]
public int Id { get; set; }
public Courselist Courses { get; set; }
public Contentsummary Summary { get; set; }
}
public string FormatCourseTitle(string courseTitle)
{
//find if last three characters are " or"
string[] words = courseTitle.Trim().ToLower().Split(' ');
int j = words.Count();
string tempStr = string.Empty;
if (words[j] == "or")
{
tempStr = courseTitle.Substring(0, courseTitle.Length - 3);
}
else
{
tempStr = courseTitle;
}
return tempStr;
}
You should use extension method as
public static class StringHelper
{
public static string FormatCourseTitle(this string courseTitle)
{
//find if last three characters are " or"
string[] words = courseTitle.Trim().ToLower().Split(' ');
int j = words.Count();
string tempStr = string.Empty;
if (words[j] == "or")
{
tempStr = courseTitle.Substring(0, courseTitle.Length - 3);
}
else
{
tempStr = courseTitle;
}
return tempStr;
}
}
Change query to
var searchResults = (from a in db.Courses
join b in db.Summary on
new { subject = a.subject, catalog = a.catalog, coursetitle = a.coursetitle.FormatCourseTitle() } equals
new { subject = b.Subject, catalog = b.Catalogno, coursetitle = b.CourseTitle } into ab
from b in ab.DefaultIfEmpty()
where a.Active == true
select new JoinModel
{
Courses = a,
Summary2020 = b
} ).ToList();
I find a way to add condition in linq query to solve this problem.
var searchResults = (from a in db.Courses
join b in db.Summary on
new { subject = a.subject, catalog = a.catalog, coursetitle = a.coursetitle.Trim().EndsWith(" or")?a.coursetitle.Substring(0,a.coursetitle.Length-3):a.coursetitle } equals
new { subject = b.Subject, catalog = b.Catalogno, coursetitle = b.CourseTitle } into ab
from b in ab.DefaultIfEmpty()
where a.Active == true
select new JoinModel
{
Courses = a,
Summary2020 = b
} ).ToList();
I am using this code for authorization on controllers.
with [Authorize(Policy = "CustomRole")]
The thing happened that after 3 or 4 request it fails with
A second operation started on this context before a previous operation completed
public class CustomRoleRequirement : AuthorizationHandler<CustomRoleRequirement>, IAuthorizationRequirement
{
public CMSContext _context = new CMSContext();
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRoleRequirement requirement)
{
var routeobj = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;
var c = routeobj.RouteData.Values.Values.ToList();
var keys = routeobj.RouteData.Values.Keys.ToList();
string area = "";
string id = "";
string controller = "";
string action = "";
string module = "";
foreach (var item in keys)
{
if (item=="area")
{
int indexs = keys.FindIndex(cc => cc == "area");
area = c[indexs].ToString();
}
else if (item == "id")
{
int indexs = keys.FindIndex(cc => cc == "id");
id = c[indexs].ToString();
}
else if (item == "controller")
{
int indexs = keys.FindIndex(cc => cc == "controller");
controller = c[indexs].ToString();
}
else if (item == "module")
{
int indexs = keys.FindIndex(cc => cc == "module");
module = c[indexs].ToString();
}
else if (item == "action")
{
int indexs = keys.FindIndex(cc => cc == "action");
action = c[indexs].ToString();
}
}
string modulelink = controller;
if (!string.IsNullOrEmpty(module))
{
modulelink = modulelink + "/" + module;
}
List<string> Roles = new List<string>();
int UserId = Auth.UserID;
string UserName = Auth.UserName;
if (UserName == "superadmin")
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
// apparently the error occurred here
var moduleobj = _context.AppModules.FirstOrDefault(q => q.Link == modulelink);
if (moduleobj != null)
{ // 69 role is assessing news module
//60 role is accessing page module
var RolesModulesobj = _context.AppRolesModules.FirstOrDefault(q => q.ModuleId == moduleobj.ModuleId && q.RolesId == Auth.RoleId);
if (RolesModulesobj != null)
{
string permissionsobj = RolesModulesobj.Permissions;
List<string> PermissionsListobj = permissionsobj.Split(',').Select(x => x.Trim()).ToList();
var FindFullAccess = PermissionsListobj.FirstOrDefault(q => q.Contains("FullAccess:true"));
if (FindFullAccess != null)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
var abc = PermissionsListobj.FirstOrDefault(q => q.Contains(action + ":true"));
if (abc != null)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
context.Fail();
return Task.CompletedTask;
}
}
}
}
}
The error occurred at this line above
var moduleobj = _context.AppModules.FirstOrDefault(q => q.Link == modulelink);
How can I make task wait before the second operation started in the method above?
You can't use a singleton DB context. You either create one each time you need one or you pool them.
I have an MVC 5 web app which talks to my class library for db needs and the class library uses Entity Framework 6 for that.
Below are 2 methods from the class library.
Both of them are initiating a new context. How do I make 'em use only one context instead, without using class level variable?
Also, if these 2 methods were to save stuff, context.SaveChanges(), how can I wrap them both into one transaction, even if the save happens in different classes?
public int FindUnknownByName(string name, string language)
{
using (var context = new ScriptEntities())
{
int languageId = this.FindLanguage(language);
var script = context.scripts.Where(l => l.Name == name && l.Unknown == true && l.LanguageId == languageId).FirstOrDefault();
if (script != null)
{
return script.Id;
}
return 0;
}
}
public int FindLanguage(string language)
{
using (var context = new ScriptEntities())
{
var lang = context.languages.Where(l => l.Name == language).FirstOrDefault();
if (lang != null)
{
return lang.Id;
}
return 0;
}
}
Make the context a private class variable.
private ScriptEntities context = new ScriptEntities()
public int FindUnknownByName(string name, string language)
{
int languageId = this.FindLanguage(language);
var script = context.scripts.Where(l => l.Name == name && l.Unknown == true && l.LanguageId == languageId).FirstOrDefault();
if (script != null)
{
return script.Id;
}
return 0;
}
public int FindLanguage(string language)
{
var lang = context.languages.Where(l => l.Name == language).FirstOrDefault();
if (lang != null)
{
return lang.Id;
}
return 0;
}
Also implement IDisposable and dispose context.
You can use extension methods:
public int FindUnknownByName(this ScriptEntities context, string name, string language)
{
int languageId = context.FindLanguage(language);
var script = context.scripts.Where(l => l.Name == name && l.Unknown == true && l.LanguageId == languageId).FirstOrDefault();
if (script != null)
{
return script.Id;
}
return 0;.
}
public int FindLanguage(this ScriptEntities context, string language)
{
var lang = context.languages.Where(l => l.Name == language).FirstOrDefault();
if (lang != null)
{
return lang.Id;
}
return 0;
}
then:
using (var context = new ScriptEntities())
{
var language = context.FindUnknownByName('name', 'language')
}
public void Updateemployee(employeeView model)
{
using (var emprep = new employeeRepository())
{
var employee= new employee();
if (emp != null)
{
emp.employee_Name = model.employee_Name;
emp.employee_Address = model.employee_Address;
emp.Email = model.Email;
emp.Contact_No = model.Contact_No;
emp.Update(emp);
}
}
}
You forgot to get by id.
public void Updateemployee(employeeView model)
{
using (var emprep = new employeeRepository())
{
var employee= new employee();
if (emp != null)
{
//here
`enter code here`emp=emprep.GetById(model.emp_Id);
emp.employee_Name = model.employee_Name;
emp.employee_Address = model.employee_Address;
emp.Email = model.Email;
emp.Contact_No = model.Contact_No;
emp.Update(emp);
}
}
}
I have mvc 5 and EF6 and never really use async in mvc before so want ask best way for run sql requests.
public ActionResult SearchTest(string id)
{
string searchtxt = UsefulClass.ConvertObjectToString(id).Replace(",", " ").Trim();
var model = new SearchResult();
if (!String.IsNullOrEmpty(searchtxt))
{
//get the data from 3 requests
var ArtistList = _db.Artists.SqlQuery("SELECT top 6 * FROM Artists WHERE CONTAINS(Name, N'Queen') and TopTracksStatus = 1 and GrabStatus > 1 order by playcount desc").ToList();
var tracks = _db.Database.SqlQuery<TrackInfo>("exec SearchTracks #SearchText=N'Queen', #TopCount=10,#LengthCount=100").ToList();
var TagsList = _db.Tags.Where(x => x.TagName.Contains(searchtxt)).Take(5).ToList();
//work with ArtistList and add to model
if (ArtistList.Any())
{
int i = 0;
foreach (var artist in ArtistList)
{
i++;
if (i == 1) //top artist
{
model.BestArtist = artist;
model.BestArtistTrackCount = _db.TopTracks.Count(x => x.Artist_Id == artist.Id);
}
else
{
model.ArtistList = ArtistList.Where(x => x.Id != model.BestArtist.Id);
break;
}
}
}
//work with tracks and add to model
if (tracks.Any())
{
model.TopTrackList = tracks;
}
//work with tags and add to model
if (TagsList.Any())
{
model.TagList = TagsList;
}
}
return View(model);
}
Here I have 3 requests which return ArtistList, tracks, TagsList and I need add them to model and then pass to view. How to do it in async way?
Try below example, hope it gives you a good idea.
public async Task<ActionResult> SearchTestAsync(string id)
{
string searchtxt = UsefulClass.ConvertObjectToString(id).Replace(",", " ").Trim();
var model = new SearchResult();
if (!String.IsNullOrEmpty(searchtxt))
{
var art = GetArtistListResulst(model);
var track = GetTracksResults(model);
var tag = GetTagsListResults(model,searchtxt);
await Task.WhenAll(art, track, tag);
}
return View(model);
}
private Task GetArtistListResulst(SearchResult model)
{
return Task.Run(() =>
{
var artistList = _db.Artists.SqlQuery("SELECT top 6 * FROM Artists WHERE CONTAINS(Name, N'Queen') and TopTracksStatus = 1 and GrabStatus > 1 order by playcount desc").ToList();
// You don't need to use foreach because the artistList is ordered by playcount already.
model.BestArtist = artistList.Take(1);
model.BestArtistTrackCount = _db.TopTracks.Count(x => x.Artist_Id == model.BestArtist.Id);
model.ArtistList = artistList.Where(x => x.Id != model.BestArtist.Id);
});
}
private Task GetTracksResults(SearchResult model)
{
return Task.Run(() =>
{
model.TopTrackList = _db.Database.SqlQuery<TrackInfo>("exec SearchTracks #SearchText=N'Queen', #TopCount=10,#LengthCount=100").ToList();
});
}
private Task GetTagsListResults(SearchResult model, string searchtxt)
{
return Task.Run(() =>
{
model.TagsList = _db.Tags.Where(x => x.TagName.Contains(searchtxt)).Take(5).ToList();
});
}