Add values to object in LINQ to SQL expression - linq

I have this contact list which I'm building using LINQ to SQL. The query to get a list of contacts is:
return db.Contacts.ToList();
In the list I also want to display each contact's primary e-mail address. To do this I first rewrite my query:
return (from db.Contacts
select c).ToList();
I found this nice way to do left joins:
return (from db.Contacts
from ce in ContactEmails.Where(x => x.ContactID == c.ContactID && c.IsPrimary).DefaultIfEmpty()
select c).ToList();
But now I want to add this PrimaryEmailAddress to my Contact object. To do this I have added a property (PrimaryEmailAddress) to the generated Contact class, using a partial class.
Is it possible in the LINQ query to add the value to c.PrimaryEmailAddress somehow? My solution right now is to create anonymous objects and then iterate them.

Here's one way to do it:
In your entity designer, create an association between your Contact class and your ContactEmail class (just guessing at your class names here). Here are some instructions on creating an association.
Then, configure your DataContext to load only your primary ContactEmail. Here are some instructions on filtering child data at the DataContext level.
And here is an entirely different way to do it:
In your partial Contact class, in your partial OnLoaded() method, query the primary ContactEmail. For example:
partial void OnLoaded()
{
// get your DataContext here
this.PrimaryContactEmail = db.ContactEmails
.Where(ce => ce.ContactID == this.ContactID && ce.IsPrimary)
.SingleOrDefault();
}

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();
}

How can I create a LINQ view?

My team is using Entity Framework 4.3.0 - Code Only with POCO classes as our ORM. Right now we use DBSets of Classes to access our 'tables'
Public Property Customers As DbSet(Of Customers)
But often we are doing soft deletes based on a IsDeleted column in LINQ, and filtering our select statements accordingly:
Dim LiveCustomers =
From C In EM.Customers
Where C.DeleteFlag = False
What I would really like to do is, instead of writing every query to include this filter, create some lower level property (possibly at our inherited DbContext level) that provides the filtered set, while maintaining strong type.
I tried this:
Public Property Customers As DbSet(Of Customer)
Public Property Customers_Live As DbSet(Of Customer)
Get
Return From C In Customers
Where C.DeleteFlag = False
End Get
Set(value As DbSet(Of Customer))
Customers = value
End Set
End Property
However that yielded me this error:
Multiple object sets per type are not supported. The object sets 'Customers' and 'Customers_Live' can both contain instances of type '__.Customer'.
A quick check on google yielded this promising result (How to: Query Objects with Multiple Entity Sets per Type) But after updating my Connection String, I'm still getting the same error.
<add name="EntityManager"
providerName="System.Data.SqlClient"
connectionString="
Data Source=xxxxxx;
Initial Catalog=xxxxxx;
User Id=xxxxxx;
Password=xxxxxx;
MultipleActiveResultSets=True"/>
So my question is, how could I effectively create a LINQ view that allows me to apply filtering, without impacting the upstream usage too drastically?
Change your property like this:
Public Property Customers As DbSet(Of Customer)
Public Property Customers_Live As IQueryable(Of Customer)
Get
Return From C In Customers
Where C.DeleteFlag = False
End Get
End Property
This is slightly different, as you won't have things like Add() or Remove(), but for a view you typically wouldn't expect to have that kind of functionality. If you want to add a new one, or remove one you should use the normal Customers property.
You could have your POCO classes inherit from a new class that has a new method that would do the filtering for you. Add something like this to the new class
--PSEUDO CODE!--
Public Function Filtered() as IEnumerable(Of Out T)
Return (From x In Me Where x.DeleteFlag).ToList()
End Function
and you could call it like:
Dim LiveCustomers =
From C In EM.Customers.Filtered
Or you could create an Interface and do a dependancy injection when you call your linq query. You'll have to google that one :)

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.

Proper way to Edit an entity in MVC 3 with the Entity Framework using Data Model First approach?

A majority of the examples I see now are either using the Code First Approach or using an older version of MVC and the Entity Framework.
Assume I have a movie to update and I get to the Edit View, in the Edit method with the Post verb, what is the proper way to update a Movie? The first Edit Method below gets me to the Edit View with the populated Movie values and the second one is the one I want to use to update, I have tried some things, but nothing updates the data.
public ActionResult Edit(int id)
{
var movie = (from m in _db.Movies1
where m.Id == id
select m).First();
return View(movie);
}
[HttpPost]
public ActionResult Edit(Movie movie)
{
try
{
// TODO: Add update logic here
//What do I need to call to update the entity?
_db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Assuming that _db is derived from ObjectContext you have two options:
Change the state of the entity to Modified:
_db.Movies1.Attach(movie);
_db.ObjectStateManager.ChangeObjectState(movie, EntityState.Modified);
_db.SaveChanges();
This marks all properties of movie as modified and will send an UPDATE statement to the database which includes all column values, no matter if the values really changed or not.
Reload the original entity from the database and apply the changes to it:
var originalMovie = (from m in _db.Movies1
where m.Id == movie.Id
select m).First();
// You actually don't need to assign to a variable.
// Loading the entity into the context is sufficient.
_db.Movies1.ApplyCurrentValues(movie);
_db.SaveChanges();
ApplyCurrentValues will mark only those properties as modified which really did change compared to the original and the UPDATE statement which will be sent to the database only includes the changed column values. So, the UPDATE statement is potentially smaller than in the first example but you have to pay the price to reload the original entity from the database.
Edit
How does the second code example work?
When you run a query using the context (_db) Entity Framework does not only retrieve the entity from the database and assign it to the left side of the query (originalMovie) but it actually stores a second reference internally. You can think of this internal context "cache" as a dictionary of key-value pairs - the key is the entity primary key and the value is the entity itself, the same object as originalMovie refers to.
ApplyCurrentValues(movie) looks up this entity in the context's internal dictionary: It takes the key property value Id of the passed in movie, searches for an entity with that key in the internal dictionary and then copies property by property from the passed in ("detached") movie to the internal ("attached") entity with the same key. EF's change tracking mechanism marks the properties as Modified which were actually different to create later the appropriate UPDATE statement.
Because of this internal reference to the original entity you do not need to hold your own reference: That's the reason why originalEntity is not used in the code. You can in fact remove the assignment to the local variable altogether.
The example would not work if you disable change tracking when you load the original entity - for example by setting _db.Movies1.MergeOption = MergeOption.NoTracking;. The example relies on enabled change tracking (which is the default setting when entities are loaded from the database).
I cannot say which of the two examples has better performance. That might depend on details like size of the entities, number of properties which have been changed, etc.
It's worth to note though that both approaches do not work if related entities are involved (for example movie refers to a category entity) and if the relationship or the related entity itself could have been changed. Setting the state to Modified and using ApplyCurrentValues both affect only scalar and complex properties of movie but not navigation properties.
Your second edit method should look something like this:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var movie = (from m in _db.Movies1
where m.Id == id
select m).First();
if (TryUpdateModel(movie))
{
_db.SaveChanges();
return (RedirectToAction("Index"));
}
return View(movie);
}

ASP.Net MVC View returned, but how can I show additional information?

I have a SQL database with has the following: Customer, Item, Clothing and Food.
Item holds a key to Clothing or Food.
Item also holds a key to Customer. Therefore a customer can have an item, which may be of food or clothing.
I am using ADO.Net Entity Framework and have this generated automatically.
I currently have the following set-up: A person may enter their ID on the webpage and this is sent via a form post where the controller picks it up and queries the database using LINQ to get the customer. The customer view (details) is then returned. I can now see all the customer details etc.
However, what I want is to be able to see the items the customer has, the different food items and clothing items, but I am unsure how to do this. I also want to be able to allow the user to edit one field of the clothes and food items tables. Any idea how I would implement this?
Here is an ActionResult in my CustomerController:
public ActionResult Details(int id)
{
var cust = (from c in dataModel.Customers
where (c.MembershipID == id)
select c).First();
return View(cust);
}
I can also write cust.Items which is the entity which I want to display in the view with the customer (their items). How would I display this in the view also?
Hopefully this makes it a little more clear on what I am trying to achieve and how.
Thanks.
Using Entity Framework, if you're tables are linked properly with the right foreign keys and all that then your Customer entity should have a property that is a collection of Items.
You could also create your own strongly typed ViewModel that has a field for Customer and implement your own properties for Clothing and Food and populate those with another query.
This question was asked last night but its similar. The guy in the question wanted information to populate a dropdown passed in. You want something similar, not for a dropdown, but to fill in textboxes to edit. How to properly populate drop downs from ViewData in controller on multiple views in ASP.NET MVC
To create a ViewModel start by creating a new class and name it CustomerAndItemsViewModel, for example.
public class CustomerAndItemsViewModel
{
public Customer Customer { get; set; }
public IQueryable<Items> Items { get; set; }
}
public ActionResult Details(int id)
{
var cust = (from c in dataModel.Customers
where (c.MembershipID == id)
select c).First();
var items = (from i in dataModel.Items
where (i.MembershipID == cust.MembershipID)
select i;
return View(new CustomerAndItemsViewModel { Customer = cust, Items = items });
}
And don't forget that you will no longer be passing a Customer to your view. So you need to change the line at the top to something like:
#model Your.Path.To.CustomerAndItemsViewModel
Typically, if you want to pass back information that is not contained in just one of your entities, you have to create a class that encompasses more than one object. So, if you want a page that displays your customer information, and all their items (which they can then edit), you would need to have a the controller action pass back a "CustomerAndItems" object (or something similarly named). This object would hold a reference to the Customer as well as a collection of their Items. (You build the CustomerAndItems object within your Action.)
Then, your view would be strongly typed to CustomerAndItems, and you can then display each piece of information as you normally would.

Resources