EF 4.1.3 Implenting Rowversion for Concurrency is not working - entity-framework

I have got a BaseEntity class which contains a, byte array called stamp, id and state, which every Entity inherits from I am mapping the stamp to
Property(t => t.Stamp).IsRequired().IsRowVersion();
this is set in BaseEntityConfiguration
which is set like this
public BaseEntityConfiguration<T> : EntityTypeConfiguration<T> where T :B aseEntity
The mapping is done like this
var baseMapConfiguration = new BaseEntityConfiguration<EntityA>();
modelBuilder.Configurations.Add(baseMapConfiguration);
var entityAMap = new EntityAMap(baseMapConfiguration);
The database has Stamp ROWVERSION NOT NULL; on the Table EntityA
I have code that handles DbUpdateConcurrencyException but this does not get caught even though the stamps are different
Also there is no where clause on with the Stamp field which I would expected
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[LastModified] AS [LastModified],
[Extent1].[CreatedDate] AS [CreatedDate],
[Extent1].[Stamp] AS [Stamp]
FROM [dbo].[EntityA] AS [Extent1]
As you seen no where statement I have also tried it from the with a normal mapping set up but still get the same result
**I have found the problem EF is getting the latest Rowversion instead of the passed in one, How can I stop this. **

if (!EntityA.Stamp.Equals(orignal.Stamp))
{
ctx.Entry(orignal).OriginalValues["Stamp"] = xmlFile.Stamp;
}
I was missing these line of codes from the DAL, this is stop EF putting the current stamp as the search criteria.

Related

EF Core completely ignores my selected properties in select

As I understand it, the following code should generate a query containing only the RouteId, RouteNo, and ShipId
var tow = (from t in _context.AllTowData
where t.RouteId == id
orderby t.RouteNo descending
select new TowDefaults {
Id = t.RouteId,
TowNo = t.RouteNo,
ShipId = t.ShipId,
LastTow = t.RouteNo
})
.FirstOrDefault();
However, I get:
SELECT v.route_id, v.route_no, v.tow_id, v.analysis_complete, v.checks_complete, v.cpr_id, v.date_created, v.date_last_modified, v.factor, v.fromportname, v.instrument_data_file, v.instrument_id, v.internal_number, v.mastername, v.message, v.miles_per_division, v.month, v.number_of_samples, v.number_of_samples_analysed_fully, v.prop_setting, v.route_status, v.sampled_mileage, v.serial_no_per_calendar_month, v.ship_speed, v.silk_reading_end, v.silk_reading_start, v.toportname, v.tow_mileage, v.validity, v.year
FROM view_all_tow_data AS v
WHERE v.route_id = '#__id_0'
ORDER BY v.route_no DESC
LIMIT 1
That's every column except the explicitly requested ShipId! What am I doing wrong?
This happens using both a SQL Server and a PostGres database
The property ShipIdis not mapped, either by a [NotMapped] annotation or a mapping instruction. As far as EF is concerned, the property doesn't exist. This has two effects:
EF "notices" that there's an unknown part the final Select and it switches to client-side evaluation (because it's a final Select). Which means: it translates the query before the Select into SQL which doesn't contain the ShipId column, executes it, and materializes full AllTowData entities.
It evaluates the Select client-side and returns the requested TowDefaults objects in which ShipId has its default value, or any value you initialize in C# code, but nothing from the database.
You can verify this by checking _context.AllTowData.Local after the query: it will contain all AllTowData entities that pass the filter.
From your question it's impossible to tell what you should do. Maybe you can map the property to a column in the view. If not, you should remove it from the LINQ query. Using it in LINQ anywhere but in a final Select will cause a runtime exception.

Breeze with stored procedure CLR error

Im trying to call a stored procedure using Entity framework.
If I go direcly to the web api method it works fine, but when calling it from breeze it causes an exception on the metadata method.
The error is :
"Could not find the CLR type for...".
Anyone know how to fix this?
I had the very same issue, but thank God I figured out a solution. Instead of using a stored procedure, you should use a view, as Breeze recognizes views as DbSet<T>, just like tables. Say you have a SQL server table that contains two tables Customers and Orders.
Customers (**CustomerId**, FirstName, LastName)
Orders (OrderId, #CustomerId, OrderDate, OrderTotal)
Now, say you want a query that returns orders by CustomerId. Usually, you would do that in a stored procedure, but as I said, you need to use a view instead. So the query will look like this in the view.
Select o.OrderId, c.CustomerId, o.OrderDate, o.OrderTotal
from dbo.Orders o inner join dbo.Customers c on c.CustomerId = o.CustomerId
Notice there is no filtering (where ...). So:
i. Create a [general] view that includes the filtering key(s) and name it, say, OrdersByCustomers
ii. Add the OrdersByCustomers view to the entity model in your VS project
iii. Add the entity to the Breeze controller, as such:
public IQueryable<OrdersByCustomers> OrdersByCustomerId(int id)
{
return _contextProvider.Context.OrdersByCustomers
.Where(r => r.CustomerId == id);
}
Notice the .Where(r => r.CustomerId == id) filter. We could do it in the data service file, but because we want the user to see only his personal data, we need to filter from the server so it only returns his data.
iv. Now, that the entity is set in the controller, you may invoke it in the data service file, as such:
var getOrdersByCustomerId = function(orderObservable, id)
{
var query = breeze.EntityQuery.from('OrdersByCustomerId')
.WithParameters({ CustomerId: id });
return manager.executeQuery(query)
.then(function(data) {
if (orderObservable) orderObservable(data.results);
}
.fail(function(e) {
logError('Retrieve Data Failed');
}
}
v. You probably know what to do next from here.
Hope it helps.

Trace Entity Framework 4.0 : Extra queries for foreign keys

In the following example, we insert an entity called taskinstance to our context. we have a foreign key FK_Contract that we set at 2.
entity.FK_Contract = 2;
context.TaskInstances.AddObject(entity);
The query generated by entity framework is a simple insert. (everything is fine)
However, the following query works differently.
int contractId = context.Contracts.Where((T) => T.Name == contractName).Single().Id;
entity.FK_Contract = contractId;
context.TaskInstances.AddObject(entity);
In the trace created by entity framework we see without surprise the query selecting the Id according a contractName but we also see an extra request looking like:
select id,... from [TaskInstances] WHERE [Extent1].[FK_Task] = #contractId
This extra query leads to many problems, especially when we work with a foreign table with millions of record. The network goes down!
Therefore we 'd like to figure out the purpose of this extra query and the way to make it disappear.
It looks like the extra query is populating a collection of tasks on the returned Contract object. Try projecting just the column you want:
int contractId = context.Contracts
.Where(T => T.Name == contractName)
.Select(T => T.Id)
.Single();

EF 4.0 Entity does not pick up new values after insert (select entity after insert)

I am using Entity Framework 4.0 POCO entity
I have mapped custom stored procedure on insert
PROCEDURE [dbo].[usp_MyTable_Insert]
(
#Value1 char(1),
#Value2 varchar(5),
#Value3 varchar(20)
....
)
AS
BEGIN TRANSACTION
INSERT INTO "dbo"."MyTable"
(
"Value1",
"Value2",
"Value3"
)
VALUES
(
#Value1,
#Value2,
#Value3
)
DECLARE #Id int
--Get the latest Id.
SET #Id = ( SELECT CAST(##IDENTITY AS INT) )
--update the table with the some values
UPDATE "dbo"."MyTable"
SET Value3 = ( SELECT SomeTableColumn
FROM SomeTable
WHERE Something = Something
)
WHERE [Id] = #Id
COMMIT TRANSACTION
SELECT #Id AS "Id"
END
It is inserting entity into database and then updating some of the columns in database
then returning identity. All pretty simple.
public int InsertRecord(RecEntity recEntity)
{
context.AddObject("RecEntities", recEntity);
context.SaveChanges();
return recEntity.Id;
}
Method insert working well.
Then i need to update current entity with values which stored procedure inserted.
I have method in my repository to retrieve data
public RecEntity SingleRecEntity(Expression> where)
{
return context.RecEntities.Single(where);
}
When i am calling this method values values inserted by stored procedure doesn't come to entity.
id = repository.InsertRecord(recEntity);
recEntity = repository.SingleBrokerPreRegistration(x => x.Id == id); // new values didnt come here from database
I run the query generated by entity framework in query analyzer, it is returning all up to date values.
But fore some reason datacontext don't want to update this entity.
Probably there is should be some ways to change this.
May be some one may explain this behaviour.
Need help.
Try the Refresh method with the StoreWins parameter.
EF does not refresh the values in case there is already an attached object with Entity Key specified unless the Refresh method is not called explicitly
If you run .Load(Objects.MergeOption.OverwriteChanges) on the collection you'll get any newly added items. If you want the deleted items to be "refreshed" you'll need to detach the entities from the collection before running .Load
Putting it all together (sorry about the vb)
For Each child in Parent.ChildCollection.ToArray()
context.Detatch(child)
Next
Parent.ChildCollection.Load(Objects.MergeOption.OverwriteChanges)
This works for me, but if there's a more elegant way I'd love to see it!

EF4, Npgsql, M:M relation, "The method or operation is not implemented." :/

I have a problem with many-to-many relation on EF4 and npgsql provider.
I have 3 tables: Order, OrderStatus and OrderStatusDict (dictionary). OrderStatus is some kind of changeLog - every order's status change is added to the OrderStatus table with its actual date and new status. I need to get all orders, which status.OrderStatusDict.OrderStatusName == "Pending", so im doing this this way:
var lst = (from o in db.Order
where o.OrderStatus
.OrderByDescending(s => s.Date)
.FirstOrDefault()
.OrdereStatusDict.OrderStatusName == "Pending"
select o).ToList();
And I get an exception:
An error occurred while preparing the
command definition. See the inner
exception for details.
Data:{System.Collections.ListDictionaryInternal}
Inner exception: {"The method or
operation is not implemented."}
And it looks that OrderByDescending kills my query, cause if I comment
.OrderByDescending(s => s.Date)
Everything works fine, but I get the oldest OrderStatus from db :/
Can u help me? Is this a provider's cause or EF problem? Do you have any ideas I could gain this other way?
I wouldn't write the query that way.
Try:
var lst = (from o in db.Order
let maxDate = o.OrderStatus.Max(s => s.Date)
where o.OrderStatus.Any(s => s.Date == MaxDate
&& s.OrdereStatusDict.OrderStatusName.Equals("Pending", StringComparison.OrdinalIgnoreCase))
select o).ToList();
I'm guessing the status comparison should be case-insensitive.
Note that my query behaves differently than yours if the max date is not unique. I'm guessing it's either unique or that my way is right.