So a drop down is used to select the users name, then click 'view' and it will display all the holidays this user has previously booked.
From here the user can click 'create new' which will bring them to a create new page.
Instead of having to re-select their name from another drop down i carried across the currentuserID and replaced the second drop down with the users ID.
Everything was working fine with 2 separate drop downs, the user could book holidays etc...
However now (after I changed the second drop down to hold the ID value) I am getting an error from my listHoliday Method in my controller:
Error: InvalidOperationException was unhandled by the user code. Sequence contains no elements.
var dbPerson1 = (from p in db.People
where p.Id == PersonId
select p).Single();
Could anyone advise what to do?
it means the linq query you're doing returns no results, to .Single() throws an exception.
try
var dbPerson1 = (from p in db.People
where p.Id == PersonId
select p).FirstOrDefault(); // or use SingleOrDefault() if People are unique
if (dbPerson1==null)
{
throw new HolidayAllocationException("Person not found");
}
else
{
// person found
if (dbPerson.HolidaysRemaining > 0)
{
AllocateHoliday(); // or whatever you need to do
}
else
{
throw new NoHolidayLeftException();
}
}
dbPerson1 will then be null if the query doesn't return anything.
hope that helps
When you get theLINQ Error "Sequence contains no elements", this is usually because you are using the First() or Single() command rather than FirstOrDefault() and SingleOrDefault().
Related
I've set up a local service and a Windows Azure database. I can access the Azure database and retrieve data from all rows but only from one column at at time.
The database has a table called People with each 'record' treated as a Person. One of the columns in the table is 'Name' and I can retrieve all of the names using:
public List<string> GetAllPeople()
{
string query = #"SELECT value Person.Name FROM DataEntities.People AS Person";
List<string> resultsAsStrings = new List<string>();
using (var context = new DataEntities())
{
ObjectQuery<string> results = context.CreateQuery<string>(query);
foreach (string result in results)
{
if (result != null)
{
resultsAsStrings.Add(result);
}
}
}
return resultsAsStrings;
}
How would I go about changing the query so that I could retrieve a list of ALL of the Person records with ALL columns in the table as opposed to just the name field?
Is there a better way to read data from an Azure table?
Cheers!
Edit:
When I change the query to:
#"SELECT value Person FROM DataEntities.People AS Person";
It returns null and my WP7 app crashes. (I also adjusted the code so that it accepted Person instead of string. E.G ObjectQuery
Try changing the call to CreateQuery:
From: CreateQuery<string>
To: CreateQuery<Person>
This is required because if you select a Person this won't be a string, but a Person.
Now, could you try not using the type (Person) as alias? Try something like this:
SELECT VALUE pers FROM DataEntities.People AS pers
And why don't you simply use context.People?
I have a table of data with a list of key value pairs in it.
Key Value
--------------------
ElementName PrimaryEmail
Email someemail#gmail.ca
Value Content/Images/logo-here.jpg
I am able to generate new items on my client webpage. When, I create a new row on the client and save it to the server by executing the following code the item saves to the database as expected.
public ViewResult Add(CardElement cardElement)
{
db.Entry(obj).State = EntityState.Added;
db.SaveChange();
return Json(obj);
}
Now, when I want to delete my objects by sending another ajax request I get a failure.
public void Delete(CardElement[] cardElements)
{
foreach (var cardElement in cardElements)
{
db.Entry(cardElement).State = EntityState.Deleted;
}
db.SaveChanges();
}
This results in the following error.
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.
I have tried other ways of deleting including find by id remove and attach and delete but obviously I am approaching in the right fashion.
I am not sure what is causing your issue, but I tend to structure my deletes as follows:
public void Delete(CardElement[] cardElements)
{
foreach (var cardElement in cardElements)
{
var element = db.Table.Where(x => x.ID == cardElement.ID).FirstOrDefault();
if(element != null)
db.DeleteObject(element);
}
db.SaveChanges();
}
although I tend to do database first development, which may change things slightly.
EDIT: the error you are receiving states that no rows were updated. When you pass an object to a view, then pass it back to the controller, this tends to break the link between the object and the data store. That is why I prefer to look up the object first based on its ID, so that I have an object that is still linked to the data store.
Hi I'm trying to do a basic update based on an id using Linq and the entity framework. I'm very new to this but I do not see the problem.
My entity class object is declared at the controller level.
gwwbnEntities db = new gwwbnEntities();
The Method grabs a querystring id and updates the user's registration status who is represented by that id.
public ActionResult ConfirmedAccount(int id)
{
var q = from u in db.user_registration
where u.id == id && u.reg_status == null
select u;
if (q.Any())
{
foreach(var item in q){
user_registration user = item;
user.reg_status = 202;
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
}
return View();
}
else
{
return RedirectToAction("RegistrationError");
}
}
Any help would be greatly appreciated! Again everything works and populates correctly, but the context object.SaveChanges() method fails everytime.
Thanks guys!
The exception you are seeing is because you have an open data reader (foreach) and you are trying to create transaction (EF does it for you) in SaveChanges(). Call SaveChanges outside the loop.
In addtion: Don't set the state to Modified - EF will detect that properties changed and will automatically set the state accordingly. You may want to do .ToList() on the q before doing anything. At the moment you are sending to queries to the database (one for .Any() and one to get entities). If you do .ToList() you will send only one query that brings entities but .Any() would be called on the list not on the database so it will be much faster and there is no trip to the database. Also ToList() force query evaluation so your foreach loop will not keep the data reader open as it will iterate on the list.
I would like to control how Linq queries my database programmatically. For instance, I'd like to query the column X, column Y, or column Z, depending on some conditions.
First of all, I've created an array of all the properties inside my class called myPropertyInfo.
Type MyType = (typeOf(MyClass));
PropertyInfo[] myPropertyInfo = myType.GetProperties(
BindingFlags.Public|BindingFlags.Instance);
The myPropertyInfo array allows me to access each property details (Name, propertyType, etc) through the index [i].
Now, how can I use the above information to control how Linq queries my DB?
Here's a sample of a query I'd like to exploit.
var myVar = from tp in db.MyClass
select tp.{expression};
Expression using myPropertyInfo[i] to choose which property (column) to query.
I'm not sure if that's the way of doing it, but if there's another way to do so, I'll be glad to learn.
EDIT:
I believe the right expression the one used by #Gabe. In fact, I'd like to make queries on the fly. Here's the reason: I've (i) a table Organizations (Ministries, Embassies, International Organizations, such as UN, UNPD, UNICEF, World Bank, etc, and services depending on them). I've (ii) an other table Hierarchy which represents the way those organizations are linked, starting by which category each one belongs to (Government, Foreign Missions, private sector, NGO, etc.)
Each column representing a level in the hierarchy, some rows will be longer while other will be shorter. Many rows' columns will share the same value (for instance 2 ministries belonging to the government, will have "Government" as value for the column 'Level 1').
That's why, for each row (organization), I need to go level by level (i.e. column by column).
if you're using Entity Framework, not LINQ to SQL, there is wonderful Entity Sql
and you can use it as
object DynamicQuery(string fieldName, object fieldValue) {
string eSql=string.Format("it.{0} = #param", fieldName);
return db.Where(eSql, fieldValue).FirstOrDefault();
}
hope this helps
MSDN has the following example, you see that you can dynamicly change strings used to access ProductID field, and as far as i remember event rename it.
using (AdventureWorksEntities advWorksContext =
new AdventureWorksEntities())
{
try
{
// Use the Select method to define the projection.
ObjectQuery<DbDataRecord> query =
advWorksContext.Product.Select("it.ProductID, it.Name");
// Iterate through the collection of data rows.
foreach (DbDataRecord rec in query)
{
Console.WriteLine("ID {0}; Name {1}", rec[0], rec[1]);
}
}
catch (EntitySqlException ex)
{
Console.WriteLine(ex.ToString());
}
}
Also you can even do the following (again from MSDN)
using (AdventureWorksEntities advWorksContext =
new AdventureWorksEntities())
{
string myQuery = #"SELECT p.ProductID, p.Name FROM
AdventureWorksEntities.Product as p";
try
{
foreach (DbDataRecord rec in
new ObjectQuery<DbDataRecord>(myQuery, advWorksContext))
{
Console.WriteLine("ID {0}; Name {1}", rec[0], rec[1]);
}
}
catch (EntityException ex)
{
Console.WriteLine(ex.ToString());
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
}
It sounds like you want to make a Queryable on-the-fly. I haven't tried it, but this might give you a start:
var myVar =
Queryable.Select(
db.MyClass,
Expression.Property(
Expression.Parameter(
typeof(MyClass), // this represents the type of "tp"
"tp"
),
myPropertyInfo[i]
)
)
how come this work
public IQueryable<Category> getCategories(int postId)
{
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
var query = from c in categories.GetAll()
join pcm in postCategoryMap.GetAll() on c.CategoryId equals pcm.CategoryId
where pcm.PostId == 1
select new Category
{
Name = c.Name,
CategoryId = c.CategoryId
};
return query;
}
but this does not
public IQueryable<Category> getCategories(int postId)
{
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
var query = from c in categories.GetAll()
join pcm in postCategoryMap.GetAll() on c.CategoryId equals pcm.CategoryId
where pcm.PostId == postId
select new Category
{
Name = c.Name,
CategoryId = c.CategoryId
};
return query;
}
The issue is most likely in the implementation of the query provider.
pcm.PostId == 1
and
pcm.PostId == postId
actually have a big difference. In the expression tree the first is generated as a ConstantExpression which doesnt need to be evaulated.
With the second, the compiler actually generates an inner class here (this is the _DisplayClassX that you see). This class will have a property (will most likely be the same name as your parameter) and the expression tree will create a MemberAccessExpression which points to the auto-generated DisplayClassX. When you query provider comes accross this you need to Compile() the Lambda expression and evaluate the delegate to get the value to use in your query.
Hope this helps.
cosullivan
The problem is not the linq itself,
you need to be sure that the context or provider object is able to fetch the data.
try testing the
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
objects and see if they are populated or if they behaving as required.
you may want to search the generated code for c__DisplayClass1 and see what you can see there. some times the generated code dose some weird things.
when you step into you code check the locals and the variable values. this may also give you some clues.
Edit : Have you tried to return a List<> collection ? or an Enumerable type?
Edit : What is the real type of the item and query may not be iterable