Get POCO object from IDataReader using Dapper - dapper

I want Dapper to give me an object for the current row of an IDataReader. That is:
T Map<T>(IDataReader reader) => ?
Is it possible?

Yes, Dapper can do it:
IEnumerable<YourPoco> result = Dapper.SqlMapper.Parse<YourPoco>(yourIDatareader);

The comment by MaurGi to use the IDataReader.GetRowParser extension led me to the Answer for Visual Basic with Dapper:
Dim parser = Dapper.SqlMapper.GetRowParser(Of YourPoco)(reader)
Dim entity = parser(reader)

Current row I'm not sure about but what you can do is use DynamicMap to Map the entire datareader data and pick what you want from there
var myObjects = Mapper.DynamicMap<IDataReader, List<MyClass>>(dataReader);

Related

how to get old and new values of modified entity : Telerik Open DataAccess

I am using Telerik Entity framework, I was looking for some method / function by means of which i can get new (current) values of a modified entity,
as i already can get old values of modified entity by doing this...
IEnumerable<string> modifiedFields = _context.GetMemberNames(_​entityName, Telerik.OpenAccess.ObjectState.Dirty);
foreach (var array in modifiedFields)
MessageBox.Show("OLD = " + _context.GetOriginalValue<string>(_entityName, array) );
how to get new values, any suggestion ?
Following extension method returns new value from the entity object in Telerik Data Access
_entityName.FieldValue<string>(nameOfPersistentField)
Returns the value of the named persistent field of the given persistent instance.

Manipulating a database in C++

I apologize if has been asked, and answered somewhere else, but I have been searching like crazy and can't find what I'm looking for.
OleDbConnection^ conn = gcnew OleDbConnection ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Milestone3testdatabase.accdb; Persist Security Info=True");
OleDbCommand^ com = gcnew OleDbCommand();
com->Connection = conn;
com->CommandText = "SELECT *FROM tblcity;";
System::Data::DataSet^ ds = gcnew System::Data::DataSet();
OleDbDataAdapter^ adapt = gcnew OleDbDataAdapter();
adapt->SelectCommand = com;
adapt->Fill(ds,"why");
dataGridView1->DataSource = ds->Tables["why"];
I am trying to figure out how to actually use the data I obtain from the database. I was shown how to put it into a gridview, BUT I don't want a gridview. I want be able to take 1 cell of the table and display it as text.
How do I convert the table into usable data for a C++ forms application?
Either modify your SELECT so that it returns only a single value by using SqlCommand.ExecuteScalar Method or extract the value from your table with the DataTable.Select Method and DataTable.Rows Property
myDataTable->Rows[rowNumber][columnNumber]

How to use predicate search with Linq-to-SQL

We are using Linq-to-SQL with SQL Server as an ORM on our new project. I have never used Linq-to-SQL before, so my question can be a bit dumb. I want to have a method that will perform a search for entities in DB by predicate, something like this:
public IEnumerable<T> Get<T>(Expression<Func<T, bool>> #where)
Could you give some advices where I can see some code samples or ideas how to implement this?
You want Where (here, originalList is any enumerable, in particular it can be a table from your context):
var filteredList = originalList.Where(element => ShouldBeIncluded(element));
Edit:
or
var filteredList =
from element in originalList
where ShouldBeIncluded(element)
select element;
And if ShouldBeIncluded is a Func<T, bool>, there's an eye-candy simplified syntax:
var filteredList = originalList.Where(ShouldBeIncluded);
Edit 2: also, note that the complete syntax is:
var filteredList = originalList.Where<TTypeOfElement>(element => ShouldBeIncluded(element));
But the generic argument can be omitted since the compiler will deduce it from the type of originalList (supposing it is an IEnumerable<TTypeOfelement>).

EF ObjectQuery<T> Context, Parameters, Connection properties equivalent on DbSet<T>

In the earlier versions of Entity Framework, we were able to reach the Context out of ObjectQuery in order to read Parameters, Connection, etc. as below:
var query = (ObjectQuery<T>)source;
cmd.Connection = (SqlConnection)((EntityConnection)query.Context.Connection).StoreConnection;
cmd.Parameters.AddRange(
query.Parameters.Select(x => new SqlParameter(
x.Name, x.Value ?? DBNull.Value)
).ToArray()
);
When I look at the DbSet<T> object, I am unable to find any equivalent of this. My purpose here is to create extensions which will manipulate the query and get the result out of it.
Here is an instance: http://philsversion.com/2011/09/07/async-entity-framework-queries
Or should I write the extension for DbContext class and work with Set method?
Any idea?
Edit
Here is what I did so far. Basic implementation so far but certainly not ready for production. Any suggestions on this?
public static async Task<IEnumerable<T>> QueryAsync<T>(this DbContext #this, System.Linq.Expressions.Expression<Func<T, bool>> predicate = null)
where T : class {
var query = (predicate != null) ? #this.Set<T>().Where(predicate) : #this.Set<T>();
var cmd = new SqlCommand();
cmd.Connection = (SqlConnection)(#this.Database.Connection);
cmd.CommandText = query.ToString();
if (cmd.Connection.State == System.Data.ConnectionState.Closed) {
cmd.Connection.ConnectionString = new SqlConnectionStringBuilder(cmd.Connection.ConnectionString) {
AsynchronousProcessing = true
}.ToString();
cmd.Connection.Open();
}
cmd.Disposed += (o, e) => {
cmd.Clone();
};
var source = ((IObjectContextAdapter)#this).ObjectContext.Translate<T>(
await cmd.ExecuteReaderAsync()
);
return source;
}
This is a nice workaround, although I don't think you can make it much more generally applicable than what you already have.
A few things to keep in mind:
- Depending on the EF query, e.g. if you are using Include or not, the columns returned in the reader might not match the properties in the type T you are passsing.
- Depending on whether you have inheritance in your model, the T that you pass to translate may not always be the right thing to materialize for every row returned.
- After the task returned by ExecuteReaderAsync completes, you still have to retrieve each row, which depending on the execution plan for the query and the latency you are getting with the server is potentially also a blocking operation.
Async support is not coming to EF in 5.0 but we worked with other teams to make sure we have all the necessary building blocks included in .NET 4.5 and the feature is pretty high in our priority list. I encourage you to vote for it in our UserVoice site.

Refreshing BindingSource after insert (Linq To SQL)

I have a grid bound to a BindingSource which is bound to DataContext table, like this:
myBindingSource.DataSource = myDataContext.MyTable;
myGrid.DataSource = myBindingSource;
I couldn't refresh BindingSource after insert. This didn't work:
myDataContext.Refresh(RefreshMode.OverwriteCurrentValues, myBindingSource);
myBindingSource.ResetBinding(false);
Neither this:
myDataContext.Refresh(RefreshMode.OverwriteCurrentValues, myDataContext.MyTable);
myBindingSource.ResetBinding(false);
What should I do?
I have solved the problem but not in a way I wanted.
Turns out that DataContext and Linq To SQL is best for unit-of-work operations. Means you create a DataContext, get your job done, discard it. If you need another operation, create another one.
For this problem only thing I had to do was recreate my DataContext like this.dx = new MyDataContext();. If you don't do this you always get stale/cached data. From what I've read from various blog/forum posts that DataContext is lightweight and doing this A-OK. This was the only way I've found after searching for a day.
And finally one more working solution.
This solution works fine and do not require recreating DataContext.
You need to reset internal Table cache.
for this you need change private property cachedList of Table using reflection.
You can use following utility code:
public static class LinqDataTableExtension
{
public static void ResetTableCache(this ITable table)
{
table.InternalSetNonPublicFieldValue("cachedList", null);
}
public static void ResetTableCache(this IListSource source)
{
source.InternalSetNonPublicFieldValue("cachedList", null);
}
public static void InternalSetNonPublicFieldValue(this object entity, string propertyName, object value)
{
if (entity == null)
throw new ArgumentNullException("entity");
if(string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException("propertyName");
var type = entity.GetType();
var prop = type.GetField(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
if (prop != null)
prop.SetValue(entity, value);
// add any exception code here if property was not found :)
}
}
using something like:
var dSource = Db.GetTable(...)
dSource.ResetTableCache();
You need to reset your BindingSource using something like:
_BindingSource.DataSource = new List();
_BindingSource.DataSource = dSource;
// hack - refresh binding list
Enjoy :)
Grid Data Source Referesh by new query instead just Contest.Table.
Simple Solution < But Working.
Whre is eg.
!!!!! Thanks - Problem Solved after no of days !!! but with so simple way ..
CrmDemoContext.CrmDemoDataContext Context = new CrmDemoContext.CrmDemoDataContext();
var query = from it in Context.Companies select it;
// initial connection
dataGridView1.DataSource = query;
after changes or add in data
Context.SubmitChanges();
//call here again
dataGridView1.DataSource = query;
I have the same problem. I was using a form to create rows in my table without saving the context each time. Luckily I had multiple forms doing this and one updated the grid properly and one didn't.
The only difference?
I bound one to the entity similarly (not using the bindingSource) to what you did:
myGrid.DataSource = myDataContext.MyTable;
The second I bound:
myGrid.DataSource = myDataContext.MyTable.ToList();
The second way worked.
I think you should also refresh/update datagrid. You need to force redraw of grid.
Not sure how you insert rows. I had same problem when used DataContext.InsertOnSubmit(row), but when I just inserted rows into BindingSource instead BindingSource.Insert(Bindingsource.Count, row)
and used DataContext only to DataContext.SubmitChanges() and DataContext.GetChangeSet(). BindingSource inserts rows into both grid and context.
the answer from Atomosk helped me to solve a similar problem -
thanks a lot Atomosk!
I updated my database by the following two lines of code, but the DataGridView did not show the changes (it did not add a new row):
this.dataContext.MyTable.InsertOnSubmit(newDataset);
this.dataContext.SubmitChanges();
Where this.dataContext.MyTable was set to the DataSource property of a BindingSource object, which was set to the DataSource property of a DataGridView object.
In code it does looks like this:
DataGridView dgv = new DataGridView();
BindingSource bs = new BindingSource();
bs.DataSource = this.dataContext.MyTable; // Table<T> object type
dgv.DataSource = bs;
Setting bs.DataSource equals null and after that back to this.dataContext.MyTable did not help to update the DataGridView either.
The only way to update the DataGridView with the new entry was a complete different approach by adding it to the BindingSource instead of the corresponding table of the DataContext, as Atomosk mentioned.
this.bs.Add(newDataset);
this.dataContext.SubmitChanges();
Without doing so bs.Count; returned a smaller number as this.dataContext.MyTable.Count();
This does not make sense and seems to be a bug in the binding model in my opinion.

Resources