Date type for a certain property with Pure Code First Hot Chocolate GraphQL - hotchocolate

I am using pure code first with Hot Chocolate but I have dateTime C# type and I am having problems with the timezone getting converted incorrectly in javascript. So I would like it to output a Date instead of a DateTime object. For now I am using
SchemaBuilder.New()
.BindClrType<DateTime, DateType>()
but this is a very brute force approach as now I can never output a DateTime type in graphQL.
Is there way to put an attribute on the property or set it up somewhere so that a specific property on a class is output as a Date instead of DateTime?

You can also use Pure Code First approach by attributing target field with GraphQLType attribute:
using HotChocolate;
public class User
{
public int Id { get; set; }
[GraphQLType(typeof(NonNullType<DateType>))]
public DateTime BirthDate { get; set; }
}

Yes, there's a pretty straightforward way of reaching that. Suppose you have some User class:
public class User
{
public int Id { get; set; }
public DateTime BirthDate { get; set; }
}
To be able to specify that BirthDate is just a date but not datetime define the User "type metadata" and specify the GraphQL type of BirthDate as "DateType":
public class UserType : ObjectType<User>
{
protected override void Configure(IObjectTypeDescriptor<User> descriptor)
{
descriptor.Field(t => t.BirthDate).Type<DateType>();
}
}
and register that type on schema building:
public void ConfigureServices(IServiceCollection services)
{
services.AddGraphQL(sp =>
SchemaBuilder.New()
.AddQueryType<Query>()
.AddType<UserType>()
.Create());
}

Related

Set options values to an entity property

I come from Django, and with Django's ORM when defining a model I can set options, for example:
class MyModel(Model):
CHOICES = (...) # List of choices here
# it has tu be a 2-tuple list
# but that's is not the point right now.
choice = IntegerField(choices=CHOICES) # Set the choices.
Now, when MyModel is used to create an instance, the attribute(property) choice can hold only values defined in CHOICES.
There is some like this for EntityFrameworkCore-2.0?
It is something like this possible?
class MyEntity
{
[choices=EnumDefiningChoices]
property enum choices { get; set; }
}
A property can have a single defined value, an int, string, etc in order to be stored in a database.
An approach is to use 2 tables, one for your entity and one for the choices.
MyEntity:
public class MyEntity
{
public int Id { get; set; }
// all the other properties
public int ChoiceId { get; set; } // Here is the refference for the choice
public virtual Choice Choice { get; set; }
}
Choice:
public class Choice
{
public int Id { get; set; }
public string Name { get; set; }
}
As you can see the ChoiceId will allow only values from the Choice table.
However if you want to use an Enum there is no "blocking" mechanism using EF, this must be implemented at the application level.
Indeed, there is a way!
With EF > 6 you can do something like this:
public enum Option
{
option_1 = 1,
option_2,
option_3
}
class SomeEntity
{
public Option Option { get; set; }
}
And you can get the enum option name with:
var option_name = Option.GetName(typeof(Option), some_entity.option_2);
Console.WriteLine(option_name);
References
Working with Enumerated Values in Entity Framework
Enum.GetName Method (Type, Object)

Value is not a convertible object

I have a simple query and Poco that I'm using with Dapper like so:
var jc = this.dbConnection.ExecuteScalar<JcUser>("SELECT loginid as Username,Password,coalesce(CustomerId,0) as CustomerId,TextProfileId,UxProfileId from \"user\" where id = #id", new {id = id});
Poco:
public class JcUser
{
public string UserName { get; set; }
public string Password { get; set; }
public int CustomerId{ get; set; }
public int TextProfileId { get; set; }
public int UxProfileId { get; set; }
}
When this executes it throws an exception with the message
Value is not a convertible object: System.String to JcUser
The stack trace ends up at: at System.Convert.ToType (System.Object value, System.Type conversionType, IFormatProvider provider, Boolean try_target_to_type)
Any ideas why its doing this?
Thanks
UPDATE: Using var jc = this.dbConnection.Query<JcUser>("SELECT loginid as Username,Password,coalesce(CustomerId,0) as CustomerId,TextProfileId,UxProfileId from \"user\" where id = #id", new {id = id}).First(); appears to work. I also realise I'm a moron and ExecuteScalar is only for one value. However, is my update the best way to retrieve only one row?
ExecuteScalar maps to the ADO.NET method of the same name. It returns at most one cell: one grid, one row, one column. As such, it is not intended for use with complex objects, and cannot work correctly in your case as you have multiple columns.
Dapper assumes you would only use that with simple types like int, string etc.
In your case, use:
var jc = this.dbConnection.Query<JcUser>(
sql, args).SingleOrDefault();
If you want to avoid a hidden List<> allocation you could also pass buffered: false.

how to map a dapper row with a .net object having a different (nested) structure

I'm looking for a way to map a row of the following table with the following object :
create table Foo (
Id BIGINT IDENTITY (1, 1) NOT NULL,
A int,
ACertainty float,
B string,
BCertainty float
....
)
public class FuzzyValue<T>{
public T Value { get; private set; }
public double Certainty { get; private set; }
}
class Foo {
public FuzzyValue<int> A { get; set;}
public FuzzyValue<string> B { get; set;}
...
}
Obviously, I can have dapper return a dynamic and do the mapping manually, but this manual tedious work kind of defeats the purpose of dapper, doesn't it?
Is there an easy way to have dapper do the mapping automatically?
I ended up writing a not so trivial mapper to do this.
If someone needs it, the source is here and there's a nuget package available here

Mapping fields in stored procedure to class properties with different names with Dapper

I have this exert from a POCO class with many fields:
public class Call
{
public int Id { get; set; }
public string Customer { get; set; }
public int StatusId { get; set; }
public int UserAssignedToId { get; set; }
public string UserAssignedToName { get; set; }
}
However my stored procedure returns different names to the properties above (in this case the Id is before:
IdCall
IdStatus
IdUserAssignedTo
This is the code I am using to execute the stored procedure:
var call = conn.Query<Call>("CallSPName", new { IdCall = callId }, commandType: CommandType.StoredProcedure).First();
How can I specify a mapping to say I would like "IdStatus" from my stored procedure map to "StatusId" in my POCO class and "IdCall" to "CallId" etc?
I don't have access to change the stored procedures as they are controlled by DBAs and older legacy systems are using them which would break if the fields got changed in the stored procedure.
Any ideas/thoughts appreciated.
The closest thing which comes to my mind is to have private properties mapped to columns returned by the stored procedure and make the public properties with the names you want setting and getting those private fields:
// ...
private int IdStatus;
public int StatusId {
get { return IdStatus; }
set { IdStatus = value; }
}
// ...

Is there an equivalent to "NotMapped" for Dapper.Net and the Dapper.Net extensions?

I've started to play with Dapper.Net, and am really loving it so far - however, I have run into one problem.
Say that I have a POCO class like:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
}
Now, using Dapper.Net and the Dapper.Net extensions, I want to simply load all instances of that data type from the DB by doing this:
string connectionString = CloudConfigurationManager.GetSetting("DBConnection");
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
IEnumerable<Types.Person> entities = cn.GetList<Types.Person>();
var forceMe = entities.ToList();
}
This works fine in the Linq setup, but when it hits the line with the .ToList(), which forces the evaluation, it blows up with "invalid column names" on FullName. Thinking that it might respect the Entity Framework DataAnnotations stuff for NotMapped, I tried adding a NotMapped attribute (after adding EF 5 to the project). This didn't work.
So, the question is, how do I tell Dapper.Net that a column isn't to be expected from the DB? Is this a problem with the extensions, trying to map a DB column for everything it sees in the model POCO? Do I need to revert to writing SQL, and explicitly ask for the columns that I want only, or is there a way to get an equivalent to NotMapped on the column?
I think the only way to to ignore certain properties from being mapped is to implement an auto class mapper, where you can specify your custom field mappings. For example:
public class CustomMapper : ClassMapper<Foo>
{
public CustomMapper()
{
Table("FooTable");
Map(f => f.Id).Column("FooId").Key(KeyType.Identity);
Map(f => f.DateOfBirth).Column("BirthDate");
Map(f => f.FirstName).Column("First");
Map(f => f.LastName).Column("Last");
Map(f => f.FullName).Ignore();
Map(f => f.Calculated).ReadOnly();
}
}
public class Foo
{
public int Id { get; set; }
public DateTime DateOfBirth { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return string.Format("{0} {1}", FirstName, LastName); }
}
}
In the above example, FullName is being ignored.
The auto-mapper also allows you to adjust table names, in case your POCO class names do not match table names.
Also, keep in mind that you must keep your custom maps in the same assembly as your POCO classes. The library uses reflection to find custom maps and it only scans one assembly.
Hope this helps,
Good luck

Resources