Performing search across multiple tables using linq - asp.net-mvc-4

I'm trying to perform a search action on my page. I have 3 tables on my database with no relation between then. I created a view model called SearchModel and I'm trying to send the query data to the view like below
I'm very new to ASP.NET*
IQueryable<SearchModel> t = Enumerable.Empty<SearchModel>().AsQueryable();
var searchD = from d in db.domains
where d.domainName.Contains(search) //search is the search string
select d;
var searchU = from u in db.users
where u.userName.Contains(search)
select u;
var searchA = from a in db.adminLists
where a.userName.Contains(search)
select a;
t.searchDomain = searchD;
t.searchAdmin = searchA;
t.searchUsers = searchU;
return view(t);
I get an error saying this
IQueryable<SearchModel>' does not contain a definition for 'searchDomain'
and no accessible extension method 'searchDomain' accepting a first argument of type
'IQueryable<SearchModel>' could be found (are you missing a using directive or an assembly reference?)
This is my view model
public class SearchModel
{
public user searchUsers { get; set; }
public adminList searchAdmin { get; set; }
public domain searchDomain { get; set; }
}
Is there something I'm missing and/or is there a better way to implement the search?

Related

ASP.NET Core 6 Write value to Page without iteration?

I am trying to write a specific value to a page in ASP.NET Core 6. I found multiple solutions with iterators but I am not able to write a single value from non-iteratable models / instances (no enumerators & lists) to a page.
public class UserViewModel
{
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
This models purpose is to get filled with values from the Identity Framework.
public UserViewModel umodel { get; set; }
Said model gets instanced, filled without any problems - it holds values (checked via console) in page.cshtml.cs:
var user = await _userManager.FindByIdAsync(id);
UserViewModel UserModel = new UserViewModel();
UserModel.UserName = user.UserName;
UserModel.Email = user.Email;
UserModel.Id = user.Id;
Console.WriteLine(UserModel.UserName);
Console.WriteLine(UserModel.Id);
Console.WriteLine(UserModel.Email);
If I try to access it on the corresponding page (page.cshtml) I can only access its name without any problems:
#Html.DisplayNameFor(model => model.umodel.Email)
When I want to access its content there is no value on the page.
#Html.DisplayFor(model => model.umodel.Email)
How can I access the values in this model on a razor page? All the solutions I found based on some kind of iterator and therefore models that had some kind of enumerator or where instanced and filled as a list.
From the code you posted, you aren't populating the page's UserViewModel property. You instantiated a different UserViewModel instance. You wrote the values of that to the Console, but the actual model property (umodel) has not been populated.
Try this in the OnGet method:
var user = await _userManager.FindByIdAsync(id);
umodel.UserName = user.UserName;
umodel.Email = user.Email;
umodel.Id = user.Id;
When rendering property values, you don't need the DisplayFor helper (unless you are using display templates). You just need to prefix the property with #:
#Model.umodel.UserName
I figured it out. There hast to be an instance of the model / class but in a specific way and naming. See following example:
Model:
public class IdentityUserModel
{
public string Id { get; set; }
public string ?UserName { get; set; }
public string ?Email { get; set; }
}
Reference to model in the Main class of the Page (page.cshtml.cs):
public IdentityUserModel IUserModel { get; set; }
Then the important part in the OnGet/OnGetAsync function(?) (page.cshtml.cs):
IUserModel = new(); // <-- instance
var user = [whatever...]
IUserModel.UserName = user.UserName;
IUserModel.Email = user.Email;
IUserModel.Id = user.Id;
Then to write on the page.cshtml:
#Model.IUserModel.Id
My understanding is that there has to be an instance of the class in die page context with exactly the same name (therefore = new() without instance name). I may have been blind but reading throug microsofts learn pages again this is was not clear at all to me.
Thanks to Mike Brind for sending me in the right direction with his input.

Not getting data while querying view using NHibernate

I am trying to query a view using NHibernate, but receving an empty result always.
View name: vw_lead_review_detail
Code snippet for View mapping:
[Class(NameType = typeof(LeadReviewDetail), Table = "vw_lead_review_detail", Lazy = false, Schema = "affiliate")]
public class LeadReviewDetail
{
[Id(Name = "LeadEventId", Column = "lead_event_id", UnsavedValue = "0")]
[Generator(1, Class = "assigned")]
public virtual int? LeadEventId { get; set; }
[Property(Column = "addition_input_value")]
public virtual string AdditionInputValue { get; set; }
}
Is there anything else do I need to change in this mapping class?
thank you!
Here is how to debug this:
Have your mapping been actually loaded? (NHibernate returns empty result if you query for a class that has no mapping.)
Enable NHibernate detailed logging and examine the SQL produced.

Best Practice with MVC4 and EF5 to apply changes

I have a CustomerOrder-view where I would like to change an existing CustomerOrder.
I have a viewmodel that very simpliefied looks something like this:
public class CustomerOrderViewModel
{
public int ID { get; set; }
public Customer Customer { get; set; }
public DateTime Date { get; set; }
public IEnumerable<OrderRow> OrderRows { get; set; }
}
public class OrderRow
{
public int id { get; set; }
public int price { get; set; }
}
public class Customer
{
public string Name { get; set; }
}
I also have a database with mapping tables / fields.
In my GET Action Method I load the Order with the help of Automapper like this:
var customerOrder = using (var ctx = new My_Entities()) {
return ctx.CustomerOrders.
Include("Orderrows").
Include("Customer").
Single(o => o.CustomerOrderID == id);
}
var model= AutoMapper.Mapper.DynamicMap<DataAccessLayer.CustomerOrder, CustomerOrderViewModel>(customerOrder);
In the View I use Knockout to bind to a viewmodel there, where the user can update the CustomerOrder. That includes editing Customer information and adding new orderrows etc.
Then in the post back a map the ViewModel back to the ObjectContext CustomerOrder:
var customerOrderToBeSaved =
AutoMapper.Mapper.DynamicMap<CustomerOrderViewModel, CustomerOrder>(
customerOrderViewModel);
try
{
using (var ctx = new MyEntities())
{
ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.CustomerOrders.ApplyCurrentValues(customerOrderToBeSaved);
...
ctx.SaveChanges();
}
}
I get the error message: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
OK, that I can understand. But how should I go about this? Can I get the existing object and apply Changes to that one, because that is really what I'd like. I've tried to look up the old one and detach it but I haven't got it to wrok.Perhaps I'm doing this in a completely wrong way. Please advice.
You should not attach customerOrderToBeSaved, see MSDN about the argument of ApplyCurrentValues.
The detached object that has property updates to apply to the original object.
So you've got to load the entity from the database into the context and then ApplyCurrentValues with the detached object that has the new values.
You don't have to load the row from the database to update it.
You can do something like this:
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
This will tell EF to issue an UPDATE SQL statement that overwrites all the columns in the record.
You can select which columns you want to update like this:
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
var entry = ctx.Entry( entity );
entry.Property( o => o.<ColumnPropertyToUpdate> ).IsModified = true;
entry.Property( o => o.<ColumnPropertyToUpdate> ).IsModified = true;
...
ctx.SaveChanges();
If you do this, EF will only include the columns you've marked as modified in the UPDATE statement.

Filter with MVC View for IEnumerable

In MVC4 there is a need to list a group of clients. I achieved this by creating 2 model ClientList and Client model. I made ClientList class as serializable. Now there is a need to apply filter condition for this model with various parameters. How to achieve this ? Here is my model.
public class Client : Paging
{
public virtual string CompanyName { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
[Serializable]
public class ClientList : Paging
{
private Client _client;
public Client Client
{
get { return _client; }
set { _client = value; }
}
}
In Data Access, am using this
while (reader.Read())
{
var rCompanyName = reader.GetOrdinal("CompanyName");
var rFirstName = reader.GetOrdinal("FirstName");
var rLastName = reader.GetOrdinal("LastName");
var resultClientList = new Client
{
CompanyName = Convert.IsDBNull(rCompanyName) ? string.Empty : reader.GetString(rCompanyName),
FirstName = Convert.IsDBNull(rFirstName) ? string.Empty : reader.GetString(rFirstName),
LastName = Convert.IsDBNull(rLastName) ? string.Empty : reader.GetString(rLastName)
};
var clients = new ClientList();
admin.Client = resultClientList;
result.Data.Add(clients);
}
In view,
#model IEnumerable<Midlab.FreightOnce.BusinessObjects.ClientList
#*i need filter condition here*#
#foreach (var item in Model)
{
--rendering list here
}
Thanks
The easiest approach for a beginner I will suggest is, to make two different methods in controller, and two views associated with these controllers. First controller function will be a get function and the view associated with this will open filter lists, user will select the filter criteria and submit it, the second controller function which is a post function will receive the request, fetch records based on filter criteria and returns the response in IEnumerable list to the second view. The Other approach is to use JQuery.ajax calls.

How to auto-load details (with conditions) associated with an entity using Ria Services?

I'm developing a project using Silverlight 4 and Entity Framework 4 and I'm trying to auto-load the details (with conditions) associated with an entity when the client loads the EntityQuery.
So far, I've been able to put in place a solution, using the Include attribute, that returns all the details associated with the master entity. What I'm missing here is to be able to filter out the details based on some criteria.
As an example, here's what my entities look like:
Entity Movie
Id (int)
[Include]
MovieLocalizedInformations (EntityCollection<MovieLocalizedInformation>)
Entity MovieLocalizedInformation
Id (int)
Movie_Id (int)
LanguageCode (eg.: en)
Title
On my DomainService object, I expose the following method:
public IQueryable<Movie> GetMovies( string languageCode )
{
return this.ObjectContext.Movies.Include( "MovieLocalizedInformations" );
}
This works fine. But when I try to add where clause to filter out the localized information based on the language code, only the movies get loaded on the client.
Is there a way to achieve the filtering in one query?
Note: I'm also using the DomainDataSource with paging on the client so the solution needs to work with that.
Any help would be greatly appreciated!
Thanks,
Jacques.
Not sure about Enitity Framework but with a LinqToSqlDomainService you use the LoadWith loadOption
to include the details entities and then use the AssociateWith LoadOption to filter the detail e.g
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Movies>(i => i.MovieLocalizedInformations);
options.AssociateWith<Movies>(i => i.MovieLocalizedInformations.Where(d=> myListOfIds.Contains(d.LocationId)));
Ok,
For efficiency reason, I decided to go with custom DTO object that fetches the localized information and flatten the result.
But, the same problem occurred when my custom DTO needed to reference another custom localized DTO.
Here is how I came to do the same as the .Include( "PropertyName" ) that the ObjectSet offers:
Entity LocalizedMovieCollection
public class LocalizedMovieCollection
{
[Key]
public int Id { get; set; }
public string Name { get; set; } (the result of a sub query based on the language)
[Include]
[Association( "LocalizedMovieCollection_LocalizedMovies", "Id", "MovieCollection_Id" )]
public IEnumerable<LocalizedMovie> Movies { get; set; }
}
Entity LocalizedMovie
public class LocalizedMovie
{
[Key]
public int Id { get; set; }
public string Name { get; set; } (the result of a sub query based on the language)
public int MovieCollection_Id { get; set; }
[Include]
[Association( "LocalizedMovie_LocalizedMovieCollection", "MovieCollection_Id", "Id", IsForeignKey = true]
public LocalizedMovieCollection MovieCollection { get; set; }
}
Then, I've declared two methods: One that returns an IQueryable of LocalizedMovieCollection and the other, an IQueryable of LocalizedMovie. (Note: There must be at least one method that returns each type of entity for the entity to get auto-generated on the Silverlight client)
My goal is to automatically load the MovieCollection associated with a Movie so the method definition to get the movies is as follow:
public IQueryable<LocalizedMovie> GetMovies( string languageCode )
{
return from movie in this.ObjectContext.Movies
join movieLocalizedInfo in this.ObjectContext.MovieLocalizedInformations
on movie equals movieLocalizedInfo.Movie
join movieCollection in this.ObjectContext.MovieCollections
on movie.MovieCollection equals movieCollection
join movieCollectionLocalizedInfo in this.ObjectContext.MovieCollectionLocalizedInformations
on movieCollection equals movieCollectionLocalizedInfo.MovieCollection
where movieLocalizedInfo.LanguageCode == languageCode && movieCollectionLocalizedInfo.LanguageCode == languageCode
select new LocalizedMovie()
{
Id = movie.Id,
Name = movieLocalizedInfo.Name
MovieCollection_Id = movieCollection.Id,
MovieCollection = new LocalizedMovieCollection(){ Id = movieCollection.Id, Name = movieCollectionLocalizedInfo.Name }
}
}
When the Silverlight client loads the query, all the LocalizedMovies and their associated LocalizedMovieCollections will be loaded into the context.