Joining asp_Users db tables in LINQ using asp.net MVC - asp.net-mvc-3

I am working on an example asp.net project using MVC, but my database is a live one which I can't make changes to (technically it's the test version of this database but my point is changes to the database aren't possible).
I use the UserID from the asp_Users table to store who makes changes to various aspects of the system, and I want to start showing the user name in various front-end tables, but how do I link the tables to get this user name?
So to clarify, I'm going to want to do this for several tables throughout the system so I was hoping I could do it using LINQ.
I can get the info I want from using the join query, but how do I pass this to my View to use?
var plans = from users in db.aspnet_Users
join import in db.Plan_Imports
on users.UserId.ToString()
equals import.User_ID
select new
{
Date = import.Date,
UserName = users.UserName
};
Sample tables
asp_Users
UserID
UserName
...
table1
ID
field1
field2
...
User_ID <--- ref to asp_Users
table2
ID
field1
field2
...
User_ID <--- ref to asp_Users

I would create a ViewModel for each view.
ViewModel is just a POCO class
public class PlanViewModel
{
public string UserName { set;get;}
public DateTime ImportDate { set;get;}
}
Then Get the Data to this ViewModel/Collection of ViewModel using LINQ Projections from your query.
public ActionResutl Show()
{
var plans = (from users in db.aspnet_Users
join import in db.Plan_Imports
on users.UserId.ToString()
equals import.User_ID
select new PlanViewModel
{
ImportDate = import.Date,
UserName = users.UserName
}).ToList();
return View(plans);
}
Now Lets make our view strongly typed to a collection of our PlanViewModel
#model List<PlanViewModel>
#foreach(var plan in Model)
{
<p>#plan.UserName</p>
<p>#plan.ImportDate.ToString()</p>
}

The solution provided by Shyju worked perfectly, and it wasn't too complex to do, however I decided that I didn't think using LINQ was appropriate in this case as the code was getting out of hand for what should be a simple call.
What I did instead was use a stored procedure to get the information, and saved it to a complex object which I passed to my view.
The code is now much neater and easier to manage, as the code above became just
var plans = db.SP_SelectImports();
Read more about stored procedure mapping here: http://dotnet.dzone.com/news/mapping-stored-procedure

Related

How can I delete all records from a table?

I've been searching for an answer on how to delete ALL records from a table using LINQ method syntax but all answers do it based on an attribute.
I want to delete every single record from the databse.
The table looks like so:
public class Inventory
{
public int InventoryId { get; set; }
public string InventoryName { get; set; }
}
I'm not looking to delete records based on a specific name or id.
I want to delete ALL recods.
LINQ method syntax isn't a must, bt I do prefer it since it's easier to read.
To delete all data from DB table I recommend to use SQL:
Trancate Table <tableName>
Linq is not meant to change the source. There are no LINQ methods to delete or update any element from your input.
The only method to change you input, is to select the (identifiers of the )data that you want to delete in some collection, and then delete the items one by one in a foreach. It might be that your interface with the source collection already has a DeleteRange, in that case you don't have to do the foreach.
Alas you didn't mention what your table was: Is it a System.Data.DataTable? Or maybe an Entity Framework DbSet<...>? Any other commonly used class that represents a Table?
If you table class is a System.Data.DataTable, or implements ICollection, it should have a method Clear.
If your tabls is an entity framework DbSet<...>, then it depends on your Provider (the database management system that you use) whether you can use `Clear'. Usually you need to do the following:
using (var dbContext = new MyDbContext(...))
{
List<...> itemsToDelete = dbContext.MyTable.Where(...).ToList();
dbContext.MyTable.RemoveRange(itemsToDelete);
dbContext.SaveChanges();
}

check if table has been created in code first approach

I am using Entity Framework's code-first approach to create tables, and I need to check if there are any entities in the database that I need to delete:
class MyDocument
{
public string Id { get; set; }
public string Text { get; set; }
}
class MyContext : DbContext
{
public DbSet<MyDocument> Documents { get; set; }
}
using (var data = new MyContext())
{
var present = from d in data.Documents
where d.Id == "some id" || d.Id == "other id"
select d;
// delete above documents
}
on first run, when there is no table yet, the LINQ expression above throws an exception:
Invalid object name 'dbo.Documents'
How do I check if the table is there and if it is not, then set present to the empty set, perhaps? Or maybe there is a way to force database/table creation before I issue the LINQ query?
EF will actually check the entire context against the DB it is attached to.
The DB can have more than the context. But not less.
So actually you check
Context.Database.CreateIfNotExists();
If the DB and context dont match and you are using automatic migrations, then you get specific object errors. But this can be misleading in terms of the how EF is handling the context to DB comparison.
You could of course try and access every DBSet in a context
Not sure how useful that is though.
EF Code first supports Migrations, either Automated or on demand.
See EF Code first migrations
Database.SetInitializer
use SetInitializer command to turn on automatic migrations for example.
The link will provide more info on the Manual/controlled approach to db migration for advanced db handling. The easier Automatic approach, is also described in the link.

MVC 3 / EF 4.2 - Editing against ViewModel, do I save against Model or ViewModel?

My first MVC3 EF 4.2 site and I'm confused on some things, currently on ViewModels when querying and saving. Please correct me if I explain this poorly, i'm not sure how to term this. The .edmx automatically created the table classes but I read it was better to create a ViewModel, considering I need to join tables to display/edit my Product completely. The controller code below is where I join tables to output a Product to edit, and then save. My question - what is the right way to save the Product, to the Product.cs model generated by DbContext or my own ProductViewModel.cs?
Is there an easier method to query a product and join the tables and then map to the viewmodels parameters, or do I keep doing all this in the controller like below?
I also want to save/update the product each time someone views/clicks on the product, so I wasn't sure if I create a separate ViewModel for updating just that parameter or again, use the Product model.
Hope that makes sense! I can explain further if needed.
private SiteForgeEntities db = new SiteForgeEntities();
public ActionResult Edit(int id)
{
var viewModel = (
from a in db.Products
join b in db.Sites
on a.SiteId equals b.SiteId
join c in db.Sections
on a.SectionId equals c.SectionId
join d in db.Affiliates
on a.AffiliateId equals d.AffiliateId
select new ProductViewModel()
{
ProductId = a.ProductId,
Product = a.Product,
Description = a.Description,
Image = a.Image,
Price = a.Price,
Clicks = a.Clicks,
Link = a.Link,
Site = b.Site,
Section = c.Section,
Affiliate = d.Affiliate
}).Single(x => x.ProductId == id);
return View(viewModel);
}
[HttpPost]
public ActionResult Edit(Product product)
{
...update database...do I pass in and save back to Product or my ProductViewModel
}
You use ViewModel to pass multiple models to the view, but when you save data, you need to save it to the appropriate model. If you are adding or modifying products, you will add items to products (using your DbContext). If you have one-to-many relationship defined between two models (in your Product.cs model you might have a property declared as:
public virtual ICollection<SomeOtherModel> SomeOtherData { get; set; }
you can use this to build a table instead of passing everything in a ViewModel. There is a nice tutorial here regarding the CRUD operations using EF4. Have a look at these short tutorials that can give you an idea about your strategy http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc.

How to simple bind joined tables from Entity Data Model 4 (.edmx) to Gridview thru c#?

I have these two tables in MySql:
[Person]
PersonId
NameFirst
NameLast
[Email]
EmailId
PersonId
EmailAddress
In VS2010, I added a new item, ADO.NET Entity Data Model. I connect to MySql and "drag-and-drop" my the two tables into the .edmx designer. Great! It has relationships and all.
Now I want to bind something like this to a Gridview WITHOUT using an EntityDataSource control:
SELECT * FROM Person INNER JOIN Email ON Person.PersonId = Email.PersonId
How am I to do this programmatically using the modern approach? I noticed in my .edmx, the tables have "Navigation Properties" and the related tables are listed there. I just don't know the concept and syntax to use it since my skills are still "DataSet-SQL Queries-DataAdapter" based.
You can start with something like this:
var query = from x in Context.Persons // Entity set on your context
from y in x.Emails // Navigation property
select new PersonProjection // Your custom class for flattened result
{
PersonId = x.PersonId,
FirstName = x.NameFirst,
LastName = x.NameLast,
EmailId = y.EmailId,
EmailAddress= y.EmailAddress
};
gridView.DataSource = query.ToList();
gridView.DataBind();

How do you re-use select statements with Entity Framework?

Given the following query:
var query = from item in context.Users // Users if of type TblUser
select new User() // User is the domain class model
{
ID = item.Username,
Username = item.Username
};
How can I re-use the select part of the statement in other queries? I.e.
var query = from item in context.Jobs // Jobs if of type TblJob
select new Job() // Job is the domain class model
{
ID = item.JobId,
User = ReuseAboveSelectStatement(item.User);
};
I tried just using a mapper method:
public User MapUser(TblUser item)
{
return item == null ? null : new User()
{
ID = item.UserId,
Username = item.Username
};
}
With:
var query = from item in context.Users // Users if of type TblUser
select MapUser(item);
But if I do this, then the framework throws an error such as:
LINQ to Entities does not recognize
the method 'MapUser(TblUser)' method,
and this method cannot be translated
into a store expression.
You can't use regular function calls in a query definition like that. LINQ needs expression trees, it can't analyze compiled functions and magically translate that to SQL. Read this for a more elaborate explanation
The techniques used in the cited article are incorporated in linqkit (factoring out predicates) and might be of help, though I'm not sure you can use the same technique for managing projections, which is what you seem to want.
The more fundamental question you should ask yourself here IMHO is whether you really need this extra mapping layer? It seems like you're implementing something that EF is already perfectly capable of doing for you...
Try making your MapUser method static.

Resources