Dapper yielding different results - c#

I have a table :
create table scheduled_task
(
scheduled_task_id serial primary key,
description varchar(255),
predicate varchar(10485760),
path varchar(255),
scheduled_task_type_id int references scheduled_task_type (scheduled_task_type_id)
);
My data object :
[Table("scheduled_task")]
public class DOScheduledTask
{
[Key]
[Column("scheduled_task_id")]
public long? ScheduledTaskId { get; set; }
[Column("description")]
public string Description { get; set;}
[Column("predicate")]
public string Predicate { get; set; }
[Column("path")]
public string Path { get; set; }
[Column("scheduled_task_type_id")]
public long? ScheduledTaskTypeId { get; set; }
}
I inserted one record into the table, that populates all fields.
I perform this in code :
var schedules = conn.Connection.Query<DOScheduledTask>("select * from scheduled_task ;");
var schedulesb = conn.Connection.GetList<DOScheduledTask>();
The first line yields a record, with everything but scheduled_task_id and scheduled_task_type_id are both null. For the second query, it is populated in full.
What am I doing wrong?

The problem is that the .Query and .GetList are from two different implementations; the one is from Dapper, and the other is from SimpleCRUD.
The solution was to create a custom mapper, due to the naming of the columns being different in code than in the DB.

Related

Cannot insert the value NULL into column 'Id', table '; column does not allow nulls

I'm seeing a strange behavior from Entity Framework. I'm using code-first approach to define a One-To-Many relationship between two entities:
public class IncomingCheck : AuditedEntityBase
{
[Key]
public int Id { get; set; }
[Required]
public virtual CheckType Type { get; set; }
[Required]
public virtual Bank Bank { get; set; }
public string Branch { get; set; }
public virtual IList<IncomingCheckHistory> History { get; set; }
}
public class IncomingCheckHistory
{
[Key]
public int Id { get; set; }
public string LongDescription { get; set; }
}
And here's I I'm trying to add an item to the History:
using (var db = new CheckDataContext())
{
foreach (var check in SelectedItems)
{
var dbCheck = await db.IncomingChecks.FindAsync(check.Id);
var history = new IncomingCheckHistory()
{
LongDescription = "something",
};
dbCheck.History.Add(history);
await db.SaveChangesAsync(); //throws the exception
}
}
But it throws an exception saying that "Cannot insert the value NULL into column 'Id'". However I've always done it like this. The database is supposed to fill the Id column itself with a unique number.
What am I missing?
Update:
Using SSProfiler, I got the query that runs on the database. It's as follows:
exec sp_executesql N'INSERT [dbo].[IncomingCheckHistories]([LongDescription], [IncomingCheck_Id])
VALUES (#0, #1)
SELECT [Id]
FROM [dbo].[IncomingCheckHistories]
WHERE ##ROWCOUNT > 0 AND [Id] = scope_identity()',N'#0 nvarchar(max) ,#1 int',#0=N'Something',#1=1
Note that scope_identity() should be getting the Id itself, correct?
Shouldn't the Id be set as the Identity?
Like this:
public class IncomingCheckHistory
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Key]
public string LongDescription { get; set; }
}
Hope that this is the solution to your problem!
Well for some strange reason the exact code worked after completely deleting the database and migrations and starting from scratch. I'm not sure why it wouldn't work without migrations. Also I had tried deleting the database before but at the time I was trying a little different code.
In any case the posted code/query should work. Also I checked the database and the columns to see if anything is different and it wasn't. I would appreciate if someone could shed some light on why it wasn't working and it is now.

How to resolve null bindings on SQLite query?

I'm using the SQLite libs and SQLite.Net to query an existing database in my Windows Phone 8.1 project. So far the connection to the db is executing fine but the records being returned are null.
I took the usual debugging steps -
1.Checked the binding types and names which map to the names in my db schema.
2.Verified the data exists in the DB.
3.Stepped through the code that queries the database, found that the db bindings are null. (This suggests to me an issue with the field mappings in my POCO)
I don't get any compile time error as such but the records being returned are null.
Question:
Does anyone know why there is an issue with the bindings provided for the database mapping?
When I stepped through the SQLite.cs class I found the binding count is 0:
Query Code:
using (var dbConn = new SQLiteConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, AppDBPath), true))
{
List<ZoneInfo> zoneInfo = dbConn.Query<ZoneInfo>("select * from " + tableName).ToList<ZoneInfo>();
ObservableCollection<ZoneInfo> zoneInfoCollection = new ObservableCollection<ZoneInfo>(zoneInfo);
return zoneInfoCollection;
}
DB Mapping POCO:
public class ZoneInfo
{
//The ObjectId property is marked as the Primary Key
[SQLite.PrimaryKey]
[Column("objectId")]
public string ObjectId { get; set; }
[Column("zone")]
public string ZoneName { get; set; }
[Column("tariff_ph")]
public int? TariffPH { get; set; }
[Column("tariff_pd")]
public int? TariffPD { get; set; }
[Column("restrictions")]
public string Restrictions { get; set; }
[Column("days_of_operation")]
public string DaysOpen { get; set; }
[Column("hours_of_operation")]
public string HoursOpen { get; set; }
public ZoneInfo()
{
}
public ZoneInfo(string objectId, string zoneName, int tariffPH, int tariffPD,
string restrictions, string daysOpen, string hoursOpen )
{
ObjectId = objectId;
ZoneName = zoneName;
TariffPH = tariffPH;
TariffPD = tariffPD;
Restrictions = restrictions;
DaysOpen = daysOpen;
HoursOpen = hoursOpen;
}
}
Database schema -
Your "DB Mapping POCO" does not match your Database schema.
[Column("tariff_ph")]
public int? TariffPH { get; set; }
[Column("tariff_pd")]
public int? TariffPD { get; set; }
Should probably be
[Column("tariff_ph")]
public float TariffPH { get; set; }
[Column("tariff_pd")]
public int TariffPD { get; set; }
Since you have floating point values in your dataset and both of them are NOT NULLABLE.
I have an minimum example here Update Record in Sqlite Window Phone 8, that creates the database, inserts some data and updates the database. See if that can help you, but I'm pretty sure your data doesn't match correctly.

Quick way of mapping a stored procedure in C# EF (using Database.SqlQuery)

I have the following in a using statement:
var result = await db.Database.SqlQuery<ModelLookup>("EXEC prGetModel", new {ManufacturerId = manufacturerId}).ToListAsync();
And a ModelLookup class :
public class ModelLookup
{
public int ManufacturerId { get; set; }
public int ModelId { get; set; }
public string ModelDesc { get; set; }
}
Some of the DB columns have a different name.
Is there a quick way (or data annotation) that I can use to take a column from the database and map to the desired field?
(without having to add the procedure to a DbContext)
Thanks,

Name table in SQLite-net

I'm building a Windows 8 C#/XAML app that uses SQLite as a storage database, and I'm trying to create multiple tables using the SQLite-net syntax.
From what I've researched so far, a table is created based off of a class. First, I've created an "Account" class via:
public class Account
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set;}
}
And then create a table and enter in initial data later on in the code via:
private static readonly string _dbPath =
Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "data.sqlite");
using (var db = new SQLite.SQLiteConnection(_dbPath))
{
db.CreateTable<Account>();
db.RunInTransaction(() =>
db.Insert(new Account()
{
Name = "MyCheckingAccount",
Type = "Checking",
})
);
}
I want to create multiple account tables, but the db.CreateTable<Account>() syntax just creates a table and the data is inserted into the columns with db.Insert(). I don't see where to enter the name of the table itself.
How do I create multiple tables, i.e. one named "BusinessAccounts" and another "PersonalAccounts" based off of the Account class?
Is there a way to do this with SQLite-net? Or do I need to write out the SQLite command explicitly somehow?
This answer seems to be outdated, in SQLite-net you can now use an attribute on a class to ovverride the table name, for example:
[SQLite.Table("table_customers")]
public class Customer
{
[MaxLength(3)]
public string code { get; set; }
[MaxLength(255)]
public string name { get; set; }
}
So it will create/update that table.
Sqlite-Net uses the class name to create the table, as well as to update the data. To do what you want, you'll need to create separate classes. One way to get around repeating common fields is to use inheritance:
public class Account
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set;}
}
public class BusinessAccounts : Account { }
public class PersonalAccounts : Account { }
To create tables:
db.CreateTable<BusinessAccounts>();
db.CreateTable<PersonalAccounts>();
To insert data:
db.Insert(new BusinessAccounts() {...});
db.Insert(new PersonalAccounts() {...});
Just a note that the above code is untested. You'll want to make sure that the tables are created correctly (e.g. with the proper primary key and autoincrement field).
Just to add that with SQLite-net, you can change the attribute of the class by implementing an initialisation overload and setting the SQLite.TableAttribute like this:
[Table("Account")]
public class Account
{
[PrimaryKey]
[AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public Account(string name = null)
{
if (!string.IsNullOrEmpty(name))
{
TableAttribute attrname = TypeDescriptor.GetAttributes(this)(0);
attrname.Name = name;
}
}
}
The name defaults to account, but if you initialize the class with a string, it sets the attribute thus you can then create a table with that name.

Code-First generated database different from DbContext Model

I've successfully setup a simple MVC4 internet app that stores model data onto a LocalDb v11.0 SQL server. I generated the database using a code-first approach, however, the Table fields in the database are different than the model database context.
public class Record
{
public int Id { get; set; }
public string PlantLocation { get; set; }
public Plant PlantType { get; set; }
public string Description { get; set; }
}
public class Plant
{
public int Id { get; set; }
public string Name { get; set; }
}
public class RecordContext : DbContext
{
public DbSet<Record> Records { get; set; }
public DbSet<Plant> Plants { get; set; }
}
dbo.Records Table
[Id] INT IDENTITY (1, 1) NOT NULL,
[PlantLocation] NVARCHAR (MAX) NULL,
[Description] NVARCHAR (MAX) NULL,
**[PlantType_Id] INT NULL,**
When i pull-up the table data, every field is populated correctly, with the PlantType_ID showing the Id of the selected Plant.
How am i supposed to used the PlantType_ID to display the ID of the Plant(or even use this stored data) in my View if PlantType_ID is not in my RecordContext?
I have tried the following to try an get at the ID but to no avail:
#Html.DisplayFor(modelItem => item.PlantType.Id)
I'm not getting build errors or runtime errors if anyone is wondering. Any insight is appreciated.
Add virtual to the plant property to allow lazyloading:
public virtual Plant PlantType { get; set; }
To avoid N+1 issues, you can instruct EF to bring back the PlantType record as part of the same initial query. Something like:
var record = db.Records.Include("PlantType").First();
We have an extension method to make it a little nicer using lambdas:
var record = c.Records.Include(i => i.PlantType).First();
public static class Extensions
{
public static IQueryable<T> Include<T, TProperty>(this IQueryable<T> source, Expression<Func<T, TProperty>> path) where T : class
{
return System.Data.Entity.DbExtensions.Include(source, path);
}
}
Edit
Alternatively you could add the following property to the Record model if all you are after is the id:
public int PlantTypeId { get; set; }
Your database structure will largely stay the same (constraint names will change) except now you can change your razor syntax to be:
#Html.DisplayFor(modelItem => item.PlantTypeId)
You do not need to add the include comments now either.
If you want to display the plant name, you could directly use:
#Html.DisplayFor(modelItem => item.PlantType.Name)
You are using primary key for display for. That's why its not showing as above said you can use display for for plant type name and other fields.

Categories

Resources