Dapper and access returning blank values - c#

I'm trying to pull data from an Access database using dapper. I have the following class defined to use the fields from the access database that I need to read. I then tried to pull the data using the code below. When I run this only blanks come back. The number of blanks match the number of records in the data table.
I tried to use a shorter sql string with the same results.
I can't find any information on this issue, does anyone have any ideas about this?
public class DLabResults
{
public int ResultsFolderNumber { get; set; }
public int Request { get; set; }
public int Release { get; set; }
public string Formulation { get; set; }
public string Container { get; set; }
public string Closure { get; set; }
public string Shipper { get; set; }
// public string Label_Back { get; set; }
// public string Label_Front { get; set; }
public string FilePath { get; set; }
}
public void LoadDapperDLabResults(List<DLabResults> items)
{
string sql = "";
//sql = "SELECT tblResults_Results.R_Project_Assignment, tblResults_Results.R_Project_Request, tblResults_Results.R_Project_Release, tblResults_Results.R_Formulation, tblResults_Results.R_Closure, tblResults_Results.R_Container, tblResults_Results.R_Shipper, '' AS Blank1, '' AS Blank2, tblResults_Results.R_Test_FullPath FROM tblResults_Results WHERE(((tblResults_Results.R_Formulation)Like '*' & [Formulation] & '*') AND ((tblResults_Results.R_Closure)Like '*' & [Closure] & '*') AND((tblResults_Results.R_Container)Like '*' & [Container] & '*') AND((tblResults_Results.R_Shipper)Like '*' & [Shipper] & '*')) ORDER BY tblResults_Results.R_Project_Assignment, tblResults_Results.R_Project_Request, tblResults_Results.R_Project_Release;";
sql = "SELECT * FROM tblResults_Results";
using (OleDbConnection connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\DavidsoJ\\Desktop\\Fixed Push Workbooks\\Redesigned Databases\\Development Lab Results Database.accdb"))
{
//var TM2 = connection.Query<DLabResults>(sql).ToList();
List<DLabResults> TM2 = connection.Query<DLabResults>(sql).ToList();
//add items to employess
if (items == null || items.Count < 1)
{
}
else
{
TM2.AddRange(items);
}
dataGridView1.DataSource = TM2;
}
}

The column names from the SQL query do not seem to match up with the properties of the desired object model DLabResults.
Either update the columns names returned from the query to match the object
SELECT tblResults_Results.R_Project_Request AS Request
/*, ... code removed for brevity */
FROM tblResults_Results
OR update the DLabResults property names to match the column names returned from the query
public class DLabResults {
public int R_Project_Request{ get; set; }
//... code removed for brevity
}
Either way, when using dapper the column names need to be mapped to object members in order for dapper to populate them.

Related

Exception when trying to make bulk insert in xamarin app with sqlite

I developed code to get the Json sent from my rest service.
I receive and threat the code and generate the sql insert statement.
I got this error:
[0:] SQLite.SQLiteException: Constraint
at SQLite.SQLiteCommand.ExecuteNonQuery () [0x000ca] in <84b9c9e630fa45bd8ac799333976ebbf>:0
at GSAN_Mobile.Repository.GsanMobileRepository`1+<>c__DisplayClass9_1[T].<BulkInsert>b__0 (Newtonsoft.Json.Linq.JToken register) [0x0002c] in D:\Projetos\Gsan\mobile\front\GSAN_Mobile\GSAN_Mobile\GSAN_Mobile\Repository\GsanMobileRepository.cs:185
at System.Collections.Generic.List`1[T].ForEach (System.Action`1[T] action) [0x0001e] in <6de48997d0c0445dbea8d4d83492d8c6>:0
at GSAN_Mobile.Repository.GsanMobileRepository`1[T].BulkInsert (Newtonsoft.Json.Linq.JArray array, System.String tableName) [0x00062] in D:\Projetos\Gsan\mobile\front\GSAN_Mobile\GSAN_Mobile\GSAN_Mobile\Repository\GsanMobileRepository.cs:180
My Bulk Insert Method
public void BulkInsert(JArray array, string tableName = "")
{
try
{
if (string.IsNullOrEmpty(tableName))
{
Type typeParameterType = typeof(T);
tableName = typeParameterType.Name;
}
using (SQLiteConnection connection = new SQLiteConnection(DataBaseUtil.GetDataBasePath()))
{
connection.BeginTransaction();
array.ToList().ForEach(register =>
{
string sql = DataBaseUtil.GenerateInsertStatement(register, tableName);
System.Diagnostics.Debug.WriteLine(sql);
var command = connection.CreateCommand(sql);
command.ExecuteNonQuery();
});
connection.Commit();
DataBaseUtil.CloseConnection(connection);
}
}
catch (Exception e)
{
LogUtil.WriteLog(e);
}
}
My utils methods
public static string GenerateInsertStatement(JToken register, string tableName)
{
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(register.ToString());
string columns = string.Join(",", data.Keys.ToList());
string values = string.Join(",", data.Values.Select(v => string.Format(#"'{0}'", v.Trim())));
return string.Format("INSERT INTO {0} ({1}) VALUES ({2}); ", tableName, columns, values);
}
public static void CloseConnection(SQLiteConnection connection)
{
connection.Dispose();
connection.Close();
}
And my ViewModel class
This is the method who I call when start to syncronize
private async Task RegistrarDados()
{
try
{
_logs.Add("Realizando o Download: ");
GenerateAtendimentoMotivosEncerramento();
GenerateHidrometrosLocalInstalacao();
GenerateHidrometrosProtecao();
GenerateFuncionarios();
GenerateGrupoFaturamento();
GenerateLigacaoAguaSituacoes();
GenerateLigacaoEsgotoSituacoes();
GenerateServicosTipo();
GenerateSistemParametros();
GenerateOrdensServico();
//GenerateContas();
int contador = _ordemServicoRepository.Count<OrdemServico>();
_logs.Add("Sincronização encerrada com sucesso!");
await App.Current.MainPage.DisplayAlert("Atenção", "Foram importados " + contador + " Ordens de Serviços!", "OK");
PodeSincronizar = true;
}
catch (Exception e)
{
LogUtil.WriteLog(e);
}
}
And this is method where the error happens
private async void GenerateOrdensServico()
{
try
{
_logs.Add("ORDENS DE SERVIÇO");
int? records = await _ordemServicoRest.GetCount();
int? limit = _sistemaParametroRepository.GetTamanhoPaginaSincMobile();
int? pages = (records / limit);
for (int i = 0; i <= pages; i++)
{
JArray ordensServico = await _ordemServicoRest.GetAllInJsonFormatPaginated(DataBaseUtil.GetPagination(i, limit.Value));
if (ordensServico == null)
{
_logs.Add("Não Contem O.S de Corte para importar!");
await App.Current.MainPage.DisplayAlert("Atenção", "Não tem O.S para importar!", "OK");
continue;
}
_ordemServicoRepository.BulkInsert(ordensServico);
}
}
catch (Exception e)
{
LogUtil.WriteLog(e);
}
}
I received paginated date because there are 8500 registers, sometimes don´t happen the error, but in the other, I don´t uderstant the erro.
And my model class
[Serializable]
public class Persistent
{
[AutoIncrement]
[PrimaryKey]
[NotNull]
[JsonProperty("id")]
public int? Id { get; set; }
}
[Table("OrdemServico")]
public class OrdemServico : Persistent
{
[JsonProperty("situacaoOS")]
public int? SituacaoOS { get; set; }
[JsonProperty("idServicoTipo")]
public int? IdServicoTipo { get; set; }
[JsonProperty("dataGeracao")]
public string DataGeracao { get; set; }
[JsonProperty("idRegistroAtendimento")]
public int? IdRegistroAtendimento { get; set; }
[JsonProperty("idgrupo")]
public int? IdGrupo { get; set; }
[JsonProperty("matriculaCliente")]
public int? MatriculaCliente { get; set; }
[JsonProperty("nomeCliente")]
public string NomeCliente { get; set; }
[JsonProperty("tipoLogradouro")]
public string TipoLogradouro { get; set; }
[JsonProperty("logradouro")]
public string Logradouro { get; set; }
[JsonProperty("numeroImovel")]
public int? NumeroImovel { get; set; }
[JsonProperty("numeroCep")]
public int? NumeroCep { get; set; }
[JsonProperty("bairro")]
public string Bairro { get; set; }
[JsonProperty("numeroHidrometro")]
public string NumeroHidrometro { get; set; }
[JsonProperty("idHidrometroProtecao")]
public int? IdHidrometroProtecao { get; set; }
[JsonProperty("idHidrometroLocalInstalacao")]
public int? IdHidrometroLocalInstalacao { get; set; }
[JsonProperty("imovel")]
public int? Imovel { get; set; }
[JsonProperty("ligacaoAguaSituacao")]
public int? LigacaoAguaSituacao { get; set; }
[JsonProperty("ligacaoEsgotoSituacao")]
public int? LigacaoEsgotoSituacao { get; set; }
[JsonProperty("sincronizada")]
public int? Sincronizada { get; set; }
}
I sent almost the time the Id, when has
My API not throw exception.
The SQLite.SQLiteException: Constraint exception and the fact that it's randomly occurring is key. You are violating a table constraint somewhere.
Your SQLite table is expecting a value that it's not receiving. For example, if one of your data fields is marked "NOT NULL" in the table and a field in your data is NULL, that constraint will fail and you will receive the exception.
You need to determine which fields have constraints and then handle the received data to ensure constraint integrity. Convert null TEXT values to String.Empty or null INTEGER fields from null to 0 if the table has a NOT NULL constraint. You will have to look at the set constraints in the data structure.
With that said you should really look into parameterized queries. Your current INSERT statement is just asking for trouble as it's vulnerable to injection. For example, if one of the value strings contains a comma, it can break your statement because SQLite doesn't know value is just a value and just treats it as part of the query commands. Parameters fix this. This could also, be what is causing your issue if you are correctly following your table constaints.
Here's a small example of how your queries should be built instead using parameters.
cmd.CommandText = "INSERT INTO MyTable (CompanyName, Address) VALUES (#Name, #Address)";
cmd.Parameters.AddWithValue("#CompanyName", myCompanyNameString);
cmd.Parameters.AddWithValue("#Address", myAddressString);
Since my dynamic query values are parameterized, I can make my values have special characters or statements like "DROP TABLE" and it will be handled correctly and protect from injection attack or exceptions from query breaking characters or words.

SQLite, Linq, Foreach: how to optimize performances?

I've developed an UWP app where I use a SQLite database to store datas that are synced.
Among these data, there a lot of tables that contain translated data. For example, for various cases, we have:
a "businness" table, which contains the id that is really used in the database
a "translation" table, which contains transaltion for the business table
The models of the "business" tables are defined like this:
public class Failure_Type : BasePoco
{
[PrimaryKey, NotNull]
public int failure_id { get; set; }
public int? function_type_id { get; set; }
public int? component_category_id { get; set; }
[MaxLength(200), NotNull]
public string description { get; set; }
public DateTime? disable_date { get; set; }
[Ignore]
public string _descriptionTr { get; set; }
}
The field "description" stores the english/default description, and the "_descriptionTr" field will store the translated description.
The models of the "translation" tables are defined like this:
public class Failure_Type_Translation : BasePoco
{
[PrimaryKey, NotNull]
public int failure_type_translation_id { get; set; }
public int? failure_type_id { get; set; }
[MaxLength(2)]
public string language { get; set; }
[MaxLength(200), NotNull]
public string description { get; set; }
}
The field "failure_type_id" is related to the business table, the other fields store the language code and the related translation.
So, after syncing datas in the SQLite database, I refresh the "translated" datas in the app and this can take a long moment. The load of the the 2 tables from the SQLite is very quickly, but the update of the "_descriptionTr" field can be very slow:
var failureType = ServiceLocator.Current.GetInstance<IRepository>().GetAll<Failure_Type>();
var failureTypeTranslations = ServiceLocator.Current.GetInstance<IRepository>().GetAll<Failure_Type_Translation>();
FailureType = new ObservableCollection<Failure_Type>();
foreach (var ft in failureType)
{
var ftt = failureTypeTranslations.FirstOrDefault(i => i.failure_type_id == ft.failure_id && i.language.ToLower().Equals(lang));
if (ftt != null)
ft._descriptionTr = ftt.description;
else
ft._descriptionTr = ft.description;
FailureType.Add(ft);
}
Is there a better way for doing this?
How could I optimize it?
Edit :
the "business" table contains 550 rows
the "translation" table contains 3500 rows
the duration of the loop is nearly 1 minute
A couple of suggestions:
Create the observable collection at once ...
FailureType = new ObservableCollection<Failure_Type>(failureType);
... so the individual additions don't fire notifications. Now use FailureType in the loop.
Instead of fetching all translations, filter them by lang:
var failureTypeTranslations = ServiceLocator.Current.GetInstance<IRepository>()
.GetAll<Failure_Type_Translation>()
.Where(l => i.language == lang);
Create a dictionary for lookup of known translations:
var dict = failureTypeTranslations.ToDictionary(ftt => ftt.failure_id);
foreach (var ft in FailureType)
{
Failure_Type_Translation ftt;
if (dict.TryGetValue(ft.failure_id, out ftt)
ft._descriptionTr = ftt.description;
else
ft._descriptionTr = ft.description;
}
I think that esp. the part failureTypeTranslations.FirstOrDefault kills performance. The query is executed for each iteration of the loop.

how to get a collection to the query made ​​in windows azure?

I have a table called Activity (Mobile service), and i add a query in reading:
Azure Script:
function read(query, user, request)
{
var param = request.parameters.UserLocation;
if(param)
{
var sql = "Select TOP 10 [NewsItemUrl], count(1) as CounterNews FROM [MobileServiceExtra].[ACTIVITY] WHERE [UserLocation] = ? GROUP BY [NewsItemUrl] ORDER BY CounterNews Desc";
mssql.query(sql,param, {success: function(results) {request.respond(statusCodes.OK, results);}});
}
//request.execute();
}
Client side:
public class ACTIVITY
{
public int Id { get; set; }
[JsonProperty(PropertyName = "UserLocation")]
public string _UserLocation { get; set; }
[JsonProperty(PropertyName = "NewsItemUrl")]
public string _NewsItemUrl { get; set; }
[JsonProperty(PropertyName = "NewsItemTitle")]
public string _NewsItemTitle { get; set; }
[JsonProperty(PropertyName = "NewsItemPublisher")]
public string _NewsItemPublisher { get; set; }
}
If I do the query in sql, I get 2 columns CounterNews and NewsItemUrl and where the Last is the number of times to repeat the url. However, I dont know how to get the data in column "CounterNews", i mean, when i want to get the query, i get to do with the Activity table (class) and obviously returns me the data correctly, but only NewsItemUrl column and the other fields are empty.
Client side:
private MobileServiceCollection<ACTIVITY, ACTIVITY> TopReadCollectionActivity;
private IMobileServiceTable<ACTIVITY> ACTIVITYTable = App.MobileService.GetTable<ACTIVITY>();
private async void LoadTop10()
{
var dict = new Dictionary<string, string>
{
{ "UserLocation", "United States" },
};
try
{
TopReadCollectionActivity = await ACTIVITYTable.WithParameters(dict).ToCollectionAsync();
}
catch (Exception ex)
{
string err = ex.Message;
}
}
if i create a class (table too)"Top10", azure give a error, because the table doen't exist. and
not want to create a new table.
how to get the query only two fields CounterNews and NewsItemUrl?
Perhaps you should just query the table directly using the OData support. This way your not confined to the structure of your table. Take a look at this for reference.
http://msdn.microsoft.com/en-us/library/windowsazure/jj677199.aspx

C# Linq to Entities Custom query to create one field in parent entity that contains a collection of child entities for binding in WPF

I am trying to create a binding source for a gridview that contains the datasource for a child gridview. I have attempted it in the following way:
I have 3 tables:
Patients: id(PK), fname, fname
Study: id(FK),study_id(PK),treatment_site,treatment_type,physician,dosimetrist
Study_Status:study_id(PK,FK),hasContours,hasPlan,isReady
I have the following model:
public class myPatient
{
public string fname { get; set; }
public string lname { get; set; }
public bool hascontours { get; set; }
public bool hasplan { get; set; }
public bool isready { get; set; }
public IEnumerable<editPatient> epr{ get; set; }
}
public class editPatient
{
public string fname { get; set; }
public string lname { get; set; }
public string txsite { get; set; }
public string txtype { get; set; }
public string physician { get; set; }
public string dosimetrist { get; set; }
}
public class myPatientList : List<myPatient>
{
public myPatientsList()
{
AddRange(getMyPatients().ToList());
}
public IEnumerable<myPatient> getMyPatients()
{
Connection plan_trackerEM = new Connection();
return from np in plan_trackerEM.patients
join ns in plan_trackerEM.studies on np.ID equals ns.Id
join nss in plan_trackerEM.study_status on ns.study_id equals nss.study_id
where ns.dosimetrist == App.userClass.user_id || ns.physician == App.userClass.user_id)
select new myPatient()
{
fname = np.fname,
lname = np.lname,
hascontours = nss.hasContours,
hasplan = nss.hasPlan,
isready = nss.isReady,
epr = getEditPatients(ns.study_id).ToList()
};
}
public IEnumerable<editPatient> getEditPatients(long study_id)
{
Connection plan_trackerEM = new Connection();
return from np in plan_trackerEM.patients
join ns in plan_trackerEM.studies on np.ID equals ns.Id
where ns.study_id == study_id
select new editPatient()
{
fname = np.fname,
lname = np.lname,
txsite = ns.treatment_site,
txtype = ns.treatment_type,
physician = ns.physician,
dosimetrist = ns.dosimetrist
};
}
}
Then I bind the data using XML
<local:myPatientsList x:Key="mPL"/>
<CollectionViewSource x:Key="MP" Source="{StaticResource mPL}"/>
<CollectionViewSource x:Key="EP" Source="{Binding epr, Source={StaticResource MP}}"/>
This errors out with: {"LINQ to Entities does not recognize the method 'System.Collections.Generic.List1[Plan_Tracker.editPatient] ToList[editPatient](System.Collections.Generic.IEnumerable1[Plan_Tracker.editPatient])' method, and this method cannot be translated into a store expression."}
Any pointers on how to get this to work would be greatly appreciated. The data that will be stored in the field "epr" will need to be editable by the user.
EDIT 2013-05-21
Ok, I might be getting closer with a very odd work around.
I removed
epr = getEditPatients(ns.study_id).ToList()
from the query results and then added after the query results:
List<mypatientResults> new_tmp_mp = new List<mypatientResults>();
foreach (mypatientResults tmp_mp in _mp)
{
tmp_mp.epr = getEditPatients(tmp_mp.sid).ToList();
new_tmp_mp.Add(tmp_mp);
}
return new_tmp_mp;
This is now runnign without error, but I have not been successful (YET) in using epr as a datasource. I have added it as a column to a datagrid for debugging and it does report it as a System.Collections.Generic.List`1[Plan_Tracker.editpatientResults], but that could be from declaring the variable and not because of the data.
I am still overmy head here and could use help figuring this out.
I am unsure the reasoning, possible that Linq does not like the tree-like structure?!? regardless the edited text above was the solution. I was able to successfully create custom hierarchy and show it in a parent/child gridview.

Reuse index transformer expressions fails on Id

I'm looking to be able to reuse some of the transform expressions from indexes so I can perform identical transformations in my service layer when the document is already available.
For example, whether it's by a query or by transforming an existing document at the service layer, I want to produce a ViewModel object with this shape:
public class ClientBrief
{
public int Id { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
// ellided
}
From this document model:
public class Client
{
public int Id { get; private set; }
public CompleteName Name { get; private set; }
public Dictionary<EmailAddressKey, EmailAddress> Emails { get; private set; }
// ellided
}
public class CompleteName
{
public string Title { get; set; }
public string GivenName { get; set; }
public string MiddleName { get; set; }
public string Initials { get; set; }
public string Surname { get; set; }
public string Suffix { get; set; }
public string FullName { get; set; }
}
public enum EmailAddressKey
{
EmailAddress1,
EmailAddress2,
EmailAddress3
}
public class EmailAddress
{
public string Address { get; set; }
public string Name { get; set; }
public string RoutingType { get; set; }
}
I have an expression to transform a full Client document to a ClientBrief view model:
static Expression<Func<IClientSideDatabase, Client, ClientBrief>> ClientBrief = (db, client) =>
new ClientBrief
{
Id = client.Id,
FullName = client.Name.FullName,
Email = client.Emails.Select(x => x.Value.Address).FirstOrDefault()
// ellided
};
This expression is then manipulated using an expression visitor so it can be used as the TransformResults property of an index (Client_Search) which, once it has been generated at application startup, has the following definition in Raven Studio:
Map:
docs.Clients.Select(client => new {
Query = new object[] {
client.Name.FullName,
client.Emails.SelectMany(x => x.Value.Address.Split(new char[] {
'#'
})) // ellided
}
})
(The Query field is analysed.)
Transform:
results.Select(result => new {
result = result,
client = Database.Load(result.Id.ToString())
}).Select(this0 => new {
Id = this0.client.__document_id,
FullName = this0.client.Name.FullName,
Email = DynamicEnumerable.FirstOrDefault(this0.client.Emails.Select(x => x.Value.Address))
})
However, the transformation expression used to create the index can then also be used in the service layer locally when I already have a Client document:
var brief = ClientBrief.Compile().Invoke(null, client);
It allows me to only have to have one piece of code that understands the mapping from Client to ClientBrief, whether that code is running in the database or the client app. It all seems to work ok, except the query results all have an Id of 0.
How can I get the Id property (integer) properly populated in the query?
I've read a number of similar questions here but none of the suggested answers seem to work. (Changing the Ids to strings from integers is not an option.)
I have a hard time following your sample fully, Really the best way to dig in to this would be with a failing self-contained unit test.
Nonetheless, let's see if I can pull out the important bits.
In the transform, you have two areas where you are working with the id:
...
client = Database.Load(result.Id.ToString())
...
Id = this0.client.__document_id,
...
The result.Id in the first line and the Id = in the second line are expected to be integers.
The Database.Load() expects a string document key and that is also what you see in __document_id.
The confusion comes from Raven's documentation, code, and examples all use the terms id and key interchangeably, but this is only true when you use string identifiers. When you use non-string identifiers, such as ints or guids, the id may be 123, but the document key is still clients/123.
So try changing your transform so it translates:
...
client = Database.Load("clients/" + result.Id)
...
Id = int.Parse(this0.client.__document_id.Split("/")[1]),
...
... or whatever the c# equivalent linq form would be.

Categories