I am receiviing this error when I try to delete rows using entity framework. Really do not understand why!
The object cannot be deleted because it was not found in the
ObjectStateManager.
public void Delete(int ticketID)
{
Modules.Entity.gmEntities context = new Modules.Entity.gmEntities();
var ticketitem = context.xticketitem.Select(p => p.TicketID == ticketID);
ticketitem.ToList().ForEach(r => context.DeleteObject(r));
context.SaveChanges();
}
By the call of context.xticketitem.Select(p => p.TicketID == ticketID); you will get a list of booleans that do not exist in context.
I think you should do something like this:
var ticketitem = context.xticketitem.Where(p => p.TicketID == ticketID);
ticketItem.ToList().ForEach(r => context.xticketitem.DeleteObject(r));
context.SaveChanges();
EDIT:
I've moved .ToList() on the next line to make differences between our snippets more evident. Let's try revise it step by step:
When you call var ticketitem = context.xticketitem.Select(p => p.TicketID == ticketID);
You are creating query that will go by all xticketitems and return whether each item's TicketID equals ticketID variable passed as an argument to your Delete method.
Result of this query is IEnumerable<bool>.
My code returns IEnumerable<xticketitem>. It's main difference.
When you call context.DeleteObject(r) your r variable is bool. and you are calling DeleteObject method on context. That mathod accepts parameter of type object (that's why you don't get error at compile time).
I'm calling DeleteObject on xticketitem ObjectSet that accepts strogly-typed parameter of xticketitem type.
Related
I am currently working on a Database-Security-System, have to make sure that in the next two minutes of this database there is no other entry that equals to true. But somehow I always end up getting a System.NotSupportedException.
My Code
public IQueryable<AuthorizationAttempt> GetSuspiciousActivity(
DateTime from,
DateTime to)
{
return GetActivity(from, to).Where(e1 =>
e1.Result == false
&& !GetActivity(
e1.AttemptDate,
e1.AttemptDate.AddMinutes(2d)
).Any(e2 => e2.Result == true));
}
Error
System.NotSupportedException: "LINQ to Entities does not recognize the method 'System.DateTime AddMinutes(Double)' method, and this method cannot be translated into a store expression."
Thanks a lot
You can't use any helper methods inside your LINQ query. Use DbFunctions instead.
var dic = context.Treasure.Include("TreasureShare")
.Where(t => t.TreasureShare.IsShared && t.TreasureShare.EvaluationContent.Contains(keyword))
.ToDictionary(t => t.ProductUrl, t => t.ProductId, EqualityComparer<string>.Default);
I got an error:
An item with the same key has already been added.
So why the equalitycomparer not work, and how to use a equalitycomparer to get different records while querying to database.
Updated:
I know IEqualityComparer can only be executed locally, but I didn't get an error like:
LINQ to Entities does not recognize the method 'System.Linq.IQueryable1[Panli.Service.Share.DataAccess.DbData.Treasure] Distinct[Treasure](System.Linq.IQueryable1[Panli.Service.Share.DataAccess.DbData.Treasure], System.Collections.Generic.IEqualityComparer`1[Panli.Service.Share.DataAccess.DbData.Treasure])' method, and this method cannot be translated into a store expression.
except I change the codes to below:
dic = context.Treasure.Include("TreasureShare")
.Where(t => t.TreasureShare.IsShared && t.TreasureShare.EvaluationContent.Contains(theme))
.Distinct(new TreasureEqualityComparer()).ToDictionary(t => t.ProductUrl, t => t.ProductId);
This is my TreasureEqualityComparer:
public class TreasureEqualityComparer : EqualityComparer<Treasure>
{
public override bool Equals(Treasure x, Treasure y)
{
return x.ProductUrl.ToLower() == y.ProductUrl.ToLower();
}
public override int GetHashCode(Treasure obj)
{
return obj.ProductUrl.ToLower().GetHashCode();
}
}
So why not throw an exception just like the Distinct() when I use ToDictionary(..) which has an IEqualityComparer param ? Anyone can explain this ?
So why not throw an exception?
The ToDictionary part is executed in memory. This is apparent when you investigate the SQL that is executed: nothing that shows any preparation for a conversion to Dictionary.
The query expression with Distinct on the other hand is translated into SQL as a whole (except it isn't because it fails). EF tries to let the database do the hard work of returning distinct values, but of course a comparer can't be translated into SQL, so this overload of Distinct() is not supported.
As for the duplicate key: apparently there are duplicate URL's (ignoring case). Maybe you should use group by.
Dictionary key has to be unique. In this case you are using ProductUrl as dictionary key and ProductId as value, unfortunately as the error indicated there are more then one records in Table having same ProductUrl. So you can't use it as a dictionary key.
Can I use an Expression Tree as an argument constraint in a FakeIteasy CallTo assertion?
Given a method on an interface with the following signature:
interface IRepository<TEntity>
{
TEntity Single(Expression<Func<TEntity, bool>> predicate);
Being called in code like so:
Flight flight = repository.Single(f => f.ID == id);
I have in mind a unit test doing something like this:
Expression<Func<Flight, bool>> myExpression = flight => flight.ID == 1;
A.CallTo(() => repository.Single(
A<Expression<Func<Flight, bool>>>.That.Matches(myExpression)))
.Returns(new Flight());
However this produces a warning: Try specifying type arguments explicitly.
I am currently having to use the Ignored property which is not ideal.
The "Matches"-method takes a lambda but you're trying to pass it the expression. What are you trying to say with the "Matches"-call? Are you matching on equality? In that case you'd just write:
A.CallTo(() => repository.Single(myExpression)).Returns(new Flight());
If you want to constrain the expression on something else you'd have to pass a predicate of the type: Func<Expression<Func<Flight, bool>>, bool> to the "Matches"-method.
Thanks Patrik,
Examining the expression was exactly what I needed to do, i.e. parse the expression (f => f.ID == id) and execute the Right side of the == to get its runtime value.
In code this looks like this:
A.CallTo(() => flightRepository.Single(A<Expression<Func<Flight, bool>>>.That
.Matches(exp => Expression.Lambda<Func<int>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == 1)))
.Returns(new Flight());
However I can't help thinking that there must be a more elegant way to achieve the same end. I'll leave that for another day though.
Thanks again,
Michael McDowell
I had the same problem while attempting to assert an expression as an argument but I was using Moq. The solution should work for you though as well...
I give most of the credit to this answer to a similar question:
Moq Expect On IRepository Passing Expression
It basically says you can do a ToString() on the expressions and compare them. It is kind of hacky but it only has one downside; the variables names in the lambda expression must match.
Here is an example...
[Test]
public void TestWhichComparesExpressions()
{
// setup
_mockRepository.Setup(x => x.GetByFilter(MatchQuery())).Returns(new List<Record>());
// execute
var records = _service.GetRecordsByFilter();
// assert
Assert.IsNotNull(records);
Assert.AreEqual(0, records.Count());
}
private static Expression<Func<DomainRecord, bool>> MatchQuery()
{
return MatchExpression(ServiceClass.QueryForTheRecords); // constant
}
// https://stackoverflow.com/questions/288413/moq-expect-on-irepository-passing-expression/1120836#1120836
private static Expression<Func<DomainRecord, bool>> MatchExpression(Expression<Func<DomainRecord, bool>> expression)
{
return It.Is<Expression<Func<DomainRecord, bool>>>(e => e.ToString() == expression.ToString());
}
I decided to put the expression into a constant on the class which used it which guaranteed it would be the same in the test if someone changed the lambda expressions's variable names.
Let's suppose I have the following code:
TEModule teModule = Context.TEModules.Where(module => module.EnumValue.Equals(text.ModuleName)).FirstOrDefault();
if (teModule == null)
{
teModule = new TEModule();
teModule.EnumValue = text.ModuleName;
Context.TEModules.AddObject(teModule);
//Context.SaveChanges();
TEModule aux = Context.TEModules.Where(module => module.EnumValue.Equals(teModule.ModuleName)).FirstOrDefault();
}
My problem is that if I keep the "SaveChanges" commented, then on the next query the aux object is always null, because Context.TEModules is empty, even when I call the "AddObject" method.
However, if I call SaveChanges after AddObject, then on the next query the aux object is not null. The problem is that I don't want to call SaveChanges so often, because this is not the only piece of code in which I add objects, and the performance goes down if I do so.
So question is: Do I have to call SaveChanges after every AddObject call, if later I need to know if the object already exists?
The purpose of linq-to-entities query is to be executed and the execution is performed in the database so if you didn't saved the entity its database representation doesn't exist.
If you need to find locally stored entities (not persisted yet) you must query ObjectStateManager instead.
var entity = Context.ObjectStateManager.GetObjectStateEntries(EntitiState.Added)
.Where(e => !e.IsRelationship)
.Select(e => e.Entity)
.OfType<TEModule>()
.FirstOrDefault(m => m.EnumValue.Equals(teModule.ModuleName));
I am re-writing this question to make it clearer what I need to do. I am trying to use Rhino-Mock to test:
public IQueryable<TxRxMode> GetAllModes()
{
return m_context.TxRxModes.Where(txRxMode => txRxMode.Active);
}
Here's the code:
var context = MockRepository.GenerateStub<IProjectContext>();
//Returns an empty list
context.Expect(c => c.TxRxModes.Where(Arg<Func<TxRxMode, bool>>.Is.Anything)).Return(new List<TxRxMode>().AsQueryable());
TxRxModes in an IObjectSet property on the context and I want it to return an empty IQueryable<TxRxMode> object when the return m_context.TxRxModes.Where(txRxMode => txRxMode.Active); code is called.
When I run this, the Expect method call throws the an ArgumentNullException:
Value cannot be null.
Parameter name: predicate
I have tried the simpler:
IObjectSet<TxRxMode> modes = MockRepository.GenerateStub<IObjectSet<TxRxMode>>();
context.Expect(c => c.TxRxModes).Return(modes);
but this throws a null reference exception when I call
return m_context.TxRxModes.Where(txRxMode => txRxMode.Active);
Basically, this is part of the method I am trying to mock, so the key question is how do I mock this Where statement?
Where is actually a global static method and you shouldn't be mocking it. It operates on an IEnumerable however and you could just mock that.
Its kind of a hassle doing it with rhino mocks however. I would recommend doing the mock manually (if you need to do it at all).