Entity Framework split string - c#

Outside of the main model I am building this list which I am them adding to a the main model that the method is returning. I wanted to know if I can do all this work inside building the main model?
Before building the main model
string Territorystring = (from p in db.Projects
join pm in db.ProjectMaterialUses on p.ProjectId equals pm.ProjectId
where projectId == p.ProjectId
select pm.Territory).FirstOrDefault();
List<string> guidStrings = TerritoryOfDistributionList.Split(',').ToList();
List<Guid> guids = guidStrings.Select(Guid.Parse).ToList();
List<Model.Country> = (from co in db.vwCountryItemDictionaries
where guids.Contains(co.CountryGUID)
select new Model.Country
{
Name = co.Name
}).ToList();
Main model
select new Project
{
TerritoryOfDistributionList = TerritoryOfDistributionList,
.....
}

When your list is used client-side, I'm assuming it will be in the form of an array. If that's true, then you could always switch your csv over to a json array (assuming your territory links aren't expecting to change):
https://learn.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver15
If the territory links are expected to change, you could always do version-chaining/updates via bulk sql statements.
Alternatively, you could set up a view, and read against that instead.

Related

I want to retrieve data from multiple tables to service payer into my project

want to retrieve data from multiple tables to service layer as I have to write database logic into service layer into my project
'KeysPlus.Service.Models.QuoteModel' to 'System.Collections.Generic.IEnumerable'.
An explicit conversion exists (are you missing a cast?)
Any help is highly appreciated!
public static IEnumerable<QuoteModel> GetJobQuotes(Login login, QuoteModel model)
{
using (var db = new KeysEntities())
{
var quotes = db.JobQuote.Where( x=> x.ProviderId == login.Id);
model = (from q in db.JobQuote
join j in db.Job on q.JobId equals j.Id
join p in db.Property on j.PropertyId equals p.Id
join a in db.Address on p.AddressId equals a.AddressId
select new QuoteModel
{
JobDescription=j.JobDescription,
QuoteAmount=q.Amount,
PropertyAddress= a.City
}).ToList();
return model;
}
}
You have a parameter in your method named model which is a single QuoteModel and you trying to set its value to a collection of QuoteModel. Remove that parameter (you not using it) and change the code to
using (var db = new KeysEntities())
{
var quotes = db.JobQuote.Where( x=> x.ProviderId == login.Id);
IEnumerable<QuoteModel> model = (from q in db.JobQuote
....
}
You have a model instance:
QuoteModel model
And you're trying to set it to a collection of model instances:
model = (from q in db.JobQuote
...
).ToList();
An apple is not a basket of apples. So you need to do one of two things, depending on what you actually want this method to do...
Return one model?
If you're looking for a specific instance from that list, then you need to add a clause to the query to return just that instance. Methods like .First() or .FirstOrDefault() can do that (or the .Single() equivalents). For example, if you want an instance which matches a specific value, it might look something like this:
model = (from q in db.JobQuote
...
).First(j => j.ID == someIdentifier);
Where of course someIdentifier is some value you have which you can use in the query. Perhaps model.ID or something like that? Depends on how you want to query your data, which we don't know here. But the point is that you need to return one model, not many models.
Additionally, you'd need to change the method's return type to QuoteModel, since you'd just be returning that one model instance.
Return many models?
Conversely, if you do want to return multiple models, then you can't put them in a variable which holds only one model. Just return the value directly:
return (from q in db.JobQuote
...
).ToList();
(Of course, then you're not even using the model variable, so why require it?)

Using a Linq query to select objects where any value of a property matches values from a list

So I am trying to filter the modules object list by userID of the currently logged in user. After that I am trying to take the moduleID of those selected object.
Using that I want to filter the reports list to only those that contain a moduleID that matches any of the the previously obtained list of moduleID.
I'm not that particularly knowledgeable on Linq and this is what I came up with:
var name = User.Identity.GetUserName();
//gets the currently logged in user:
ApplicationUser currentUser =
(ApplicationUser)db.Users.Single(x => x.UserName == name);
//gets moduleID's for modules owned by current user:
var modules = (from i in db.Modules
where i.User == currentUser
select i.ModuleID);
var Reports = from u in db.Reports
where u.moduleID == modules
select u;
I'm having problems with the last portion trying to incorporate the contains method into the statement.
Any help would be appreciated.
You could simplify the multiple queries to one if I'm inferring your table structure correctly:
var name = User.Identity.GetUserName();
var reports = from r in db.Reports
join m in db.Modules on r.moduleID equals m.ModuleID
where m.User.UserName == name
select r;
You can't compare a int to a IEnumerable<int>. However you can check if the moduleID is found within the modules like this :
where modules.Contains(u.moduleID)
You're on the right track.
var Reports = from u in db.Reports
where modules.Contains(u.moduleID)
select u;
Or using lambda:
var reports = db.Reports.Where(u => modules.Contains(u));
You're close. In Linq its a little backwards from standard SQL. In its case you want to see if the report's module id is contained in the list of modules, so it would look like this:
var Reports = from u in db.Reports
where modules.Contains(u.moduleID)
select u;
Use the navigation properties if you have a one to many relation you could do directly in your Where clause:
var name = User.Identity.GetUserName();
var Reports = db.Reports.Where(x => x.Module.User.Name == name);

Lazy loading vs individually loading each property for foreign keys

Since I am using Entity Framework 6 Database First and my database has all of its relationships setup, my EDMX auto generates navigation properties for me whether they are object lists or individual objects. This way I can lazy load using .Include(x => x.NavProperty).
How would I handle something such as the following using lazy loading that was previously done in a stored procedure that would return a list of OrderDetailDto which has a string property called MaterialDescription?
SELECT od.*, IIF(m.Description is null, od.Description, m.description) as MaterialDescription
FROM OrderDetail od
LEFT OUTER JOIN Material m ON od.MaterialId = m.Id
I am really trying to avoid doing this but I might end up ignoring all of the build in navigation properties and create a Dto for each entity and strictly add the properties I want bound to it. Then do selects like the following:
using (var context = new AppContext())
{
var odList = (from od in context.MaterialPODetails
join m in context.Materials on od.MaterialId equals m.Id into gj
from m in gj.DefaultIfEmpty()
select OrderDetailDto
{
Id = od.Id,
MaterialPOId = od.MaterialPOId,
MaterialId = od.MaterialId,
Description = od.Description,
Unit = od.Unit,
Quantity = od.Quantity,
UnitPrice = od.UnitPrice,
Archived = od.Archived,
DateCreated = od.DateCreated,
CreatedBy = od.CreatedBy,
DateModified = od.DateModified,
ModifiedBy = od.ModifiedBy,
// navigation properties
MaterialDescription = (m == null ? obj.Description : m.Description)
}).ToList();
return odList;
}
}
Please give me any advice possible on how to avoid. I want to avoid creating Dtos and simply use the Auto Generated EF classes with the virtual properties but it seems that there is limitations and performance differences. I won't be able to do the If statement that I want to do with the left outer join.
I don't know if this is proper terminology but I believe what I want is to still use Flattened objects but not have to create Dtos.

Automapper and MvcPager3 working together

I want to add Pagination to one of my views using MvcPager3. This would be simple, except that I'm already using AutoMapper to map my model to a simplied viewmodel.
List<Call> calls = (from p in db.Calls orderby p.ID descending select p).ToList();
var viewModel = new List<CallListItem>();
Mapper.Map(calls, viewModel);
return View(viewModel);
I thought it might be as simple as replacing this line
var viewModel = new List<CallListItem>();
with this
var viewModel = new PagedList<CallListItem>();
But PagedList has a constructor which takes a list of items. Since automapper is going to be doing this for me I thought I might be able to pass null, but it doesn't work.
Anybody have experience with using these two components in harmony?
Thanks
Edit:
Found an alternative to MvcPager called PagedList. It's much better because it has a StaticPagedList class which you can use for data which has already been paged.
You could paginate the view model after the mapping:
var calls = (from p in db.Calls orderby p.ID descending select p).ToList();
var viewModel = Mapper
.Map<IEnumerable<Call>, IEnumerable<CallListItem>>(calls)
.ToPagedList(currentPage, pageSize);
return View(viewModel);
Alternately, you can paginate first and map afterwards by using StaticPagedList.
This worked for me:
var calls = (from p in db.Calls orderby p.ID descending select p).ToPagedList();
var viewModel = Mapper.Map<IEnumerable<CallListItem>>(calls);
return new StaticPagedList<CallListItem>(viewModel, calls);
I did this because I did not want to list all the objects in order to page later.
Based on this nice post.

Databinding to LINQ query result in Silverlight

I am retrieving simple LINQ query, but I am joining with two table and binding data with ListBox.
I am not able to properly show the item into the ListBox.
once I remove new item and select only keyword using it will work properly, but I want to join two table with select new key word it wil not allow to bind data with ListBox.
my code is like.
This will not allow to bind with ListBox.
var newPeople = (from p in clsGeneral.db.Table<SmartFXAttribes>()
join q in clsGeneral.db.Table<CategoryAttribes>() on p.catId equals q.ID
where p.catId == ((SmartFX.CategoryAttribes)((ComboBox)cmbPrintSize).SelectedValue).ID
select new
{
p.ID,
p.ImageHeight,
p.Imageoutline,
p.ImageUnit,
p.ImageWidth,
p.NoofPic,
p.TextboxCaption,
p.CanvasPixelHeight,
p.CanvasPixelWidth,
p.CanvasUnit,
p.catId,
q.FileName
}).ToList();
lstThumbnail.ItemsSource = newPeople;
This code will work fine.
var newPeople =
(from p in clsGeneral.db.Table<SmartFXAttribes>()
join q in clsGeneral.db.Table<CategoryAttribes>() on p.catId equals q.ID
where p.catId == ((SmartFX.CategoryAttribes)((ComboBox)cmbPrintSize).SelectedValue).ID
select p).ToList();
lstThumbnail.ItemsSource = newPeople;
Thanks!
The problem is that the first query creates an anonymous-typed object, but Silverlight cannot do data binding against an anonymous-typed object (anonymous types are internal and Silverlight's reflection capabilities do not allow accessing internal types from other assemblies). Your second query returns objects of a named type so it works just fine.
The best solution to this is to declare a public type containing public properties for everything you want to return from your first query and return an instance of that instead.
You can work around it with this hack, though.

Categories