How do I add select parameters when reading data for the View? - sql

I am making an MVC 3 web application in asp.net. It is supposed to be like a little community where users can send messages to each other (and later on also to specified groups of people). So in my database I have the tables Users and Messages. A row in Messages (a message) contains both sender and receiver (a foreign key to the Users table) plus some other info such as title, send date and of course the message text.
When a user come to the index page for logged in users, I want to show all messages that have been sent to this user, or sent from this user. Therefore, when reading the messages from the Messages table I want to use a parameter, the id of the logged in user (which I can access in my controller). So I have the parameter but I don't know how to use it when getting the results. I know there must be a way to do this correctly instead of putting in a bunch of sql and starting connections right in the code the ugly way.
As you maybe can see now, all the messages from the table will be retrieved and sent to the View for displaying it to the user.
The CommunityEntities line is part of the whole Entity Framework thing, not exactly sure how that stuff works yet, although I have been following some tutorials:
(Creating-an-entity-framework-data-model-for-an-asp-net-mvc-application)
(Mvc-music-store-part-1).
UserController.cs:
...
CommunityEntities db = new CommunityEntities();
public ActionResult Index()
{
var messages = db.Messages.ToList();
return View(messages);
}
...
CommunityEntities.cs:
public class CommunityEntities : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Message> Messages { get; set; }
}
EDIT: I did try that thing with db.Database.SqlQuery(...) but that seemed wrong, seeing as the point is to do this correctly and "neat". This is for my education and my teachers are going to be picky at the structure of the application.

You need a where clause:
var messages = db.Messages.Where( m => m.SentById == id || m.SentToId == id ).ToList();

Related

Saving user ID with Entity Framework

I'm using entity framework v6.2.0 and ASP Net MVC to create a web page to access a database and edit the entries. The overwhelming majority of the code is the basic framework provided for me. The database is connected successfully and entries can be viewed, edited, and deleted. Additionally I have implemented some rudimentary paging, searching, and sorting as instructions are provided by microsoft on how to implement those. The last thing I need to do before the site is truly functional is to pull the userID from the users login and save that as the EnteredBy field before saving any changes or new entries to the table.
if (ModelState.IsValid)
{
string currentUserId = User.Identity.GetUserId();
yasukosKitchen.EnteredBy = currentUserId;
db.YasukosKitchens.Add(yasukosKitchen);
db.SaveChanges();
return RedirectToAction("Index");
}
This code seems very simple, and I added using Microsoft.AspNet.Identity; so it compiles fine. However when I attempt to test this code the EnteredBy field is left blank or null.
My search for information turned up a post suggesting the use of the following line of code.
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
However when I attempt to add that I get an error, the ApplicationUser cannot be found and Users does not exist in this context. The fix for this is probably staring me in the face but my lack of experience and comprehension is killing me.
As suggested: My question is, how do I get and/or correctly add the UserId to my database entry?
If your Database Context has an entry to your YasukosKitchen table; usually something like this,
public virtual DbSet<YasukosKitchen> YasukosKitchens {get; set;}
and YasukosKitchen table has a column 'EnteredBy' (string 128 length), then you can post the value for the logged in user's Id straight from the View.
Add this to the very beginning of the Create view.
#using Microsoft.AspNet.Identity
#using Microsoft.AspNet.Identity.EntityFramework
At the end of the form just before the submit button, add this code.
#Html.HiddenFor(model => model.EnteredBy, new { #Value = User.Identity.GetUserId() })
I'm not sure what is the functionality of 'Users' table.

Query for entities which are not joined with some other certain entities

I am trying to implement a custom task scheduler system.
I have a following (simplified) entity model:
class User
{
public virtual long UserId { get; set; }
public virtual string Name { get; set; }
}
class Task
{
public virtual long TaskId { get; set; }
public virtual long? UserId { get; set; }
public virtual string TaskName { get; set; }
public virtual Guid SchedulerSessionUid { get; set; }
}
For now, corresponding SQL tables are straight forward with fields mapping exactly as they appear in the classes above.
The scheduler is a C# Windows console app. It will run once per day.
It should work in a following way (simplified):
generate a Guid for current session
try selecting next User entity, which does not already have a task scheduled in the current scheduler session (Guid compare); if no such a User found, go to the step 5.
add a new Task for the user selected in the step 2.
go to step 2.
exit the application
It seems a pretty trivial problem, but I have a problem implementing the second step. I have tried various queries, but there are some rules which always stop me.
Here are some rules which I have to obey while implementing the step 1:
I am not allowed to modify the User class or User SQL table
I may modify Task class and table, if it will help to solve the problem
I may add a new table or a stored procedure, if it will help
I have to implement it in a way which is as compatible with NHibernate and LINQ as possible
there might exist also some tasks which are not associated with any User object (the scheduler will ignore those, but still I have to keep that in mind while designing the SQL/LINQ query and NHibernate mapping).
Here are some real world example how it should work.
Users
-----------------
UserId Name
-----------------
1 First
2 Second
Tasks
--------------------------------------------------------
TaskId UserId SchedulerSessionUid
--------------------------------------------------------
1 NULL 6d8e48d0-4e92-477e-82fa-cd957e7dc201
2 1 d213cfc8-23d6-49fb-b4e3-9ff3b60af6c4
3 1 9ee042df-88a7-447e-adbd-e7551ed50ae5
1.Now when the Scheduler runs, it generates a current session id = 76ea57fa-8c89-4c05-9ca2-a450b1f8a032.
Now it should issue the magical LINQ query to NHibernate LINQ
provider to get a User entity
In the first iteration the query should return the User entity with
UserId=1 because there are no tasks in the current session for that
User yet
Now the Scheduler creates a new task with UserId=1,
SchedulerSessionUid=76ea57fa-8c89-4c05-9ca2-a450b1f8a032.
In the next iteration the Scheduler should get a User with UserId=2. Again, a new task is inserted with UserId=2, SchedulerSessionUid=76ea57fa-8c89-4c05-9ca2-a450b1f8a03.
In the next iteration the Scheduler should get no users, so it exits.
What LINQ query could I use to get the User for the step 2? What changes in my SQL schema and entity model do I need?
If I now follow you correctly, you need to get a (just one) user for which there are no tasks with the given session id. Am I correct?
Users.Where(u => !Tasks.Any(t = > t.UserId == u.UserId && t.SchedulerSessionUid == curSession)).FirstOrDefault()
Edit:
Since you're doing several spins through this, would you perhaps be faster doing:
foreach(var user toDealWith Users.Where(u => !Tasks.Any(t = > t.UserId == u.UserId && t.SchedulerSessionUid == curSession)))
{
//do stuff
}
Rather than keep hitting the database each time?

RavenDB - retrieving part of document

I am playing with Raven DB for few days and I would like to use it as a storage for my Web chat application. I have document which contains some user data and chat history - which is big collection chat messages.
Each time I load user document chat history is also loaded, even if I need only few fields like: user name, password and email.
My question is: how to load only part of document from database ?
Tomek,
You can't load a partial document, but you can load a projection.
session.Query<User>()
.Where(x=>x.Name == name)
.Select( x=> new { x.Name, x.Email });
That will load only the appropriate fields
From what I've seen you can do this (based on the original "User" scenario above):
public class UserSummary
{
public string Name { get; set; }
public string Email { get; set; }
}
Then you can do this:
documentSession.Query<User>().AsProjection<UserSummary>();
Looking at the Raven server it spits this out as part of the query:
?query=&pageSize=128&fetch=Name&fetch=Email&fetch=Id
So it looks like it is querying and returning only a subset of the original object, which is good.
This also works:
documentSession.Query<User>().Select( x=> new User { Name = x.Name, Email= x.Email })
But I don't think that is as clean as returning a UserSummary object.
Some follow up questions to those who have posted responses:
The link to RaccoonBlog has this example:
https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Infrastructure/Indexes/PostComments_CreationDate.cs
Would that method be preferred over the .AsProjection()? What is the difference between the two approaches?
Tomek, you cannot load only a part of the document.
However, I understand the problem in your case. I recommend to use two seperate documents for each user: One that actually contains the users data (name, passwordhash, email, etc.) and one that contains all the users messages. That way, it is still very cheap to load all the messages of a user and also to load a list of user for general purposes.
This is actually quite similar to how one would model a blog-domain, where you have a post and the posts comments. Take a look at RaccoonBlog to see how this works.

EF : MVC : ASP: TPH Error - Store update, insert, or delete ... number of rows (0). Entities ... modified or deleted ... Refresh ObjectStateManager

Error Message: "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
Hello All,
I've created a Code First TPH(Table Per Hierarchy) within MVC and EF with a SQL compact db.
Here's the Class diagram/Hierarchy:
Class Diagram
Client and SalesRep both inherit the BaseUser class. The Key is "UserID" and it's coded with the Data Annotation [Key](I'm aware that 'ID' should set it as well)
Here's where I'm at: I can seed the database with a few entries. When I try to set the "UserID" in the seeding method it seems to ignore it and just apply the UserID in numerical order...(Seems ok to me?)
furthermore here's my DbContext
public class SiteDB:DbContext
{
public DbSet<BaseUser> AllUsers { get; set; }//enable TPH
public DbSet<SalesRep> SalesReps { get; set; }
public DbSet<Client> Clients { get; set; }
}
Next,
I have created a controller for Clients -> ClientsController with strongly typed Razor Views. With this. I now have a CRUD for the Clients. I can create new Clients without any issue, but when I try to edit a Client entry, I get the error message stated above.
I did notice something interesting I stepped through the code and the error is happening on the db.SaveChanges();
When the client is passed back into the ActionResult Edit method the UserID=0! Bizarre? I'm not sure if this is a bug or if it's an actual issue that's causing this.
UserID=0
Your help with this is appreciated. Thanks!
To modify an entity you need to get it from the database: when you pass back the modified values in the Edit action you need to retrive the entity from the db object, getting it by ID, apply the modified values and save it.
Here an example:
public ActionResult Edit(int id, MyModel model){
using (SiteDBdb = new SiteDB()){
Client cl = (from c in db.Clients where c.id == id select c).First();
cl.MyProp = model.MyProp;
...
db.SaveChanges();
}
...
}

How do I serialize/deserialize a NHibernate entity that has references to other objects?

I have two NHibernate-managed entities that have a bi-directional one-to-many relationship:
public class Storage
{
public virtual string Name { get; set; }
public virtual IList<Box> Boxes { get; set; }
}
public class Box
{
public virtual string Box { get; set; }
[DoNotSerialize] public virtual Storage ParentStorage { get; set; }
}
A Storage can contain many Boxes, and a Box always belongs in a Storage. I want to edit a Box's name, so I send it to the client using JSON. Note that I don't serialize ParentStorage because I'm not changing which storage it's in.
The client edits the name and sends the Box back as JSON. The server deserializes it back into a Box entity.
Problem is, the ParentStorage property is null. When I try to save the Box to the database, it updates the name, but also removes the relationship to the Storage.
How do I properly serialize and deserialize an entity like a Box, while keeping the JSON data size to a minimum?
I would recommend you send a DTO to the client for display purposes (and it should contain the unique database ID). Then send the boxId + the new name back up to the server from the client (there is no need to send the entire DTO back). The server can do a database lookup using the ID to get the box object, update the name field to the one sent from the client, and save the box to the database.
There is no need in this scenario to serialize an NHibernate object, that just adds a lot of complexity and no value.
I would guess that ParentStorage is null because it is being lazily loaded. Either configuring it to be fetched eagerly or forcing a read by calling the getter before serialization may help make sure the Storage is serialized, and depending on your ID scheme this may work (I don't know for sure).
The gains from serialization in this case seem minimal, and may have unexpected consequences as the Box and Storage classes evolve. It seems simpler to send up a single string for the name, load the Box, set the string, and save that object. Then you don't have to worry as much about the optimizations Hibernate does underneath.