I am using Dapper to Update and Insert Access DB. Code is working not throwing exception but its not updating the value in DB. Below is my code
sql.Append("UPDATE drugs_repository SET drug_name = #DrugName ");
sql.Append(" WHERE id = #DrugId");
var parameters = new
{
DrugName = objDrug.DrugName,
DrugId = objDrug.DrugId
};
var t = connection.Query<string>(sql.ToString(), parameters);
Can someone please let me know what exactly I am missing in the above code?
When I hardcode the value than its updating in the DB. So probably its related to parameter.
If you are nervous about possible side-effects from removing the .OrderBy() in the Dapper code then a workaround would be to name your parameters in such a way that they will sort in the same order that they appear in the SQL command. For example, I suspect that the unmodified Dapper code would probably work okay if the parameters were named #1DrugName and #2DrugId.
Related
Is it possible to generate a raw SQL statement for insert/update operations using nHibernate without actually executing them? Assuming of course that everything (mappings, connectionStrings, etc.) is properly configured?
The closest thing I've found is to call:
Session.SessionFactory.GetClassMetadata(typeof(Client))
Which returns an object of type SingleTableEntityPersister containing SQLIdentityInsertString, that looks like this:
INSERT INTO Client (FirstName, LastName) values (?, ?)
But it would still require me to bind all of the properties manually, and on top of that SQLIdentityInsertString is a protected property. Are there any proper ways of doing that?
Okay, the closest thing I've found is to construct your own sql query with a string builder. First you need to extract your class metadata:
var metaData = Session.SessionFactory.GetClassMetadata(typeof(Client)) as SingleTableEntityPersister;
Then you can retrieve other information, such as:
var propertyNames = metaData.PropertyNames;
var tableName = metaData.TableName;
var firstPropertyValue = metaData.GetPropertyValue(client, propertyNames[0], EntityMode.Poco);
Once you have that information you can construct your own query manually. Not exactly the solution I wanted, but it's as close as it gets, I think.
However, one thing to note is that Session.CreateSQLQuery(string) method is currently bugged, and as a result SetParameter method doesn't work with more than 10 named parameters. There already seems to be a bug report created for this on NHbiernate's Jira.
I'm completely new to LINQ. I'm just trying to do some easy stuff but I got an error:
Invalid object name 'dbo.grupyTowarowe'.
I could have sworn this worked couple min ago and I didn't change anything.
This is the code:
var papier = from GrupyTowarowe in dbContext.grupyTowarowes
where GrupyTowarowe.typ == "moneta"
select new
{
GrupyTowarowe.grupa
};
dataGridView1.DataSource = papier;
The error is shown on the DataGridView.
Check the schema of 'grupyTowarowe' - it may be different if you've moved to a different database. Eg, your dev database might have it as schema 'dbo' but the next database could create your object under a different schema. If that is the case, use the ALTER SCHEMA command in SSMS.
When you create an anonymous object using "select", you must assign to a field so that it can be referenced.
select new
{
Grupa = GrupyTowarowe.grupa
}
However, it really looks like all you want is the result. In that case, you do not create an object you simply select the object that is returned.
var papier = from GrupyTowarowe in dbContext.grupyTowarowes
where GrupyTowarowe.typ == "moneta"
select GrupyTowarowe;
Correction:
The original syntax for the anonymous class is legal. I have lived and breathed this stuff for over a decade. I just never tried this syntax. You learn new things every day.
Update:
This answer is mostly incorrect, especially since the OP's error is related to the Entity Framework, not Linq. But I am leaving it (feel free to downvote) since there are useful comments that explain why the answer is wrong.
I have genereated a EF Model from a MS SQL database and I have included both StoredProcedures and Tables. I want to implement stored procedures in my project. Which is the best approach that has more advantages?
var data = db.DARs.SqlQuery("db.sp_GetEmployees").ToList();
or
var data2 = db.sp_GetEmployees().ToList();
Here is full code:
private UniversityEntities1 db = new UniversityEntities1();
public List<DAR> test()
{
var data = db.DARs.SqlQuery("db.sp_GetEmployees").ToList();
var data2 = db.sp_GetEmployees.ToList();
return data;
}
It's better to use mapper stored procedutes instead of calling plain SQL text (in your exmple data2).
It's better becouse EF generates result row with particular datatypes that your stored procedure returns. And you don't need to map it in your code - EF do it for you. Then you can work with result like you work with collection that contains objects with typed fields.
I would also like to add that by using
var data2 = db.sp_GetEmployees().ToList();
you make sure that renaming the procedure results in a compile error every time you are using that statement. These can be fixed quickly.
If you are just using a string you will have to remember to replace all occurences of the procedure name in the whole project. The project itself will compile.
I trying to do the following query using dapper but its always returning a empty result set. First I tried to remove the WHERE clause in order to isolate the problem but that didn't work. After that I added a alias to the C.NAME column in the SELECT clause but didn't work either.
private const string SelectClaims =
#"SELECT C.NAME FROM CLAIMS C
INNER JOIN USERS_CLAIMS UC ON C.ID = UC.ID_CLAIM
WHERE UC.ID_USER = #Id";
using (var conn = new FbConnection(connectionString))
{
var claims = conn.Query<string>(SelectClaims, new { user.Id });
return claims;
}
If I replace the query above for this right here everything works fine:
SELECT NAME FROM CLAIMS
To be honest I am not sure if you are using Dapper properly since you are selecting named column and mapping it to simple string - I believe Dapper doesn't see 'Name' property as fails silently. I guess you should try either Query<T> with strongly typed object or use Query<dynamic> to avoid unnecessary class creation.
So, I put this aside and go do something else and after I came back to try to solve my problem everything was working fine. I didn't change anything in my code and surprisingly its working right now.
I don't know if is possible that a pending transaction in my MiTeC Interbase Query was blocking me to see the current records from the database. I try to simulate this again and now its always returning the records that I need (better that than nothing, hehe).
For clarification, its perfect fine to use a string as the returning data type, do a simple join in sql parameter to a Query method or don't use a alias for the returning column at all (only if all columns matches your C# property names or you just have a column directing to a string like me).
Please see the following situation:
I do have a CSV files of which I import a couple of fields (not all in SQL server using Entity Framework with the Unit Of Work and Repository Design Pattern).
var newGenericArticle = new GenericArticle
{
GlnCode = data[2],
Description = data[5],
VendorId = data[4],
ItemNumber = data[1],
ItemUOM = data[3],
VendorName = data[12]
};
var unitOfWork = new UnitOfWork(new AppServerContext());
unitOfWork.GenericArticlesRepository.Insert(newGenericArticle);
unitOfWork.Commit();
Now, the only way to uniquely identify a record, is checking on 4 fields: GlnCode, Description, VendorID and Item Number.
So, before I can insert a record, I need to check whether or not is exists:
var unitOfWork = new UnitOfWork(new AppServerContext());
// If the article is already existing, update the vendor name.
if (unitOfWork.GenericArticlesRepository.GetAllByFilter(
x => x.GlnCode.Equals(newGenericArticle.GlnCode) &&
x.Description.Equals(newGenericArticle.Description) &&
x.VendorId.Equals(newGenericArticle.VendorId) &&
x.ItemNumber.Equals(newGenericArticle.ItemNumber)).Any())
{
var foundArticle = unitOfWork.GenericArticlesRepository.GetByFilter(
x => x.GlnCode.Equals(newGenericArticle.GlnCode) &&
x.Description.Equals(newGenericArticle.Description) &&
x.VendorId.Equals(newGenericArticle.VendorId) &&
x.ItemNumber.Equals(newGenericArticle.ItemNumber));
foundArticle.VendorName = newGenericArticle.VendorName;
unitOfWork.GenericArticlesRepository.Update(foundArticle);
}
If it's existing, I need to update it, which you see in the code above.
Now, you need to know that I'm importing around 1.500.000 records, so quite a lot.
And it's the filter which causes the CPU to reach almost 100%.
The `GetAllByFilter' method is quite simple and does the following:
return !Entities.Any() ? null : !Entities.Where(predicate).Any() ? null : Entities.Where(predicate).AsQueryable();
Where predicate equals Expression<Func<TEntity, bool>>
Is there anything that I can do to make sure that the server's CPU doesn't reach 100%?
Note: I'm using SQL Server 2012
Kind regards
Wrong tool for the task. You should never process a million+ records one at at time. Insert the records to a staging table using bulk insert and clean (if need be) and then use a stored proc to do the processing in a set-based way or use the tool designed for this, SSIS.
I've found another solution which wasn't proposed here, so I'll be answering my own question.
I will have a temp table in which I will import all the data, and after the import, I'll execute a stored procedure which will execute a Merge command to populate the destinatio table. I do believe that this is the most performant.
Have you indexed on those four fields in your database? That is the first thing that I would do.
Ok, I would recommend trying the following:
Improving bulk insert performance in Entity framework
To summarize,
Do not call SaveChanges() after every insert or update. Instead, call every 1-2k records so that the inserts/updates are made in batches to the database.
Also, optionally change the following parameters on your context:
yourContext.Configuration.AutoDetectChangesEnabled = false;
yourContext.Configuration.ValidateOnSaveEnabled = false;