How to handle identity fields in GraphQL SPQR - graphql-spqr

Let's say I have
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="trade_id")
int tradeId;
When I query this from the database, I will want to get the tradeId. However, when performing a Create, obviously I won't have the tradeId, since the Database is going to generate it when I insert it.
input TradeInput {
tradeId: Int!
...
But the schema SPQR is generating for me is setting this field to Not Null, however.
So my question is, how can prevent this field from automatically coming up as Not Null, so I won't have to send it down on Creates, but can retrieve it.

An int simply can not be null. But you have a few options:
Turn it into an ID scalar type (using #GraphQLId) instead of an Int
Give it a default value via #GraphQLInputField
Use Integer instead of int, as Integer is nullable

Related

Add record to table with FK

I have a table UserStoreName,
Columns are :
int Id
string UserNameId (as a FK of the table AspNetUsers (Column Id))
sring StoreName
I have a page AddStore, a very simple page where user just enter the store name into the StoreName Field.
I already know the UserNameId, i'm taking it from the User.
So when user populate the storeName field and click submit i just need to add a record to the table UserStoreName.
sounds easy.
when i click submit the AddStore function from the controller is giving me ModelState.IsValid = false.
reason for that is cause userNameId is a required field.
i want to populate that field in the AddStore
function but when we get there the modelState is already invalid because of a required field in userStoreNameId enter code here
Here is the AddStore in case it will help :
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult AddStore(UserStoreName userStoreName)
{
userStoreName.UserNameId =
(_unitOfWork.ApplicationUser.GetAll().Where(q => q.UserName == User.Identity.Name).Select(q => q.Id)).FirstOrDefault();
userStoreName.UserName = User.Identity.Name;
userStoreName.IsAdminStore = false;
if (ModelState.IsValid)
{
_unitOfWork.UserStoreName.Add(userStoreName);
_unitOfWork.Save();
return RedirectToAction(nameof(Index));
}
return View(userStoreName);
}
Any idea what am i doing wrong? new to asp.net core mvc, its my first project.
Thanks :)
Thank you
If the UserNameId field is required, it must be supplied to pass model validation.
There are two ways around this. First, you could create a View Model, with just the fields you plan on actually submitting, and use it in place of the userStoreName variable. Then in the controller action, you can just instantiate a new UserStoreName object, and fill out the fields.
Alternatively, you could pass the UserNameId variable to the view, and populate the model client side using a hidden field, so it passes validation when returned to the controller. Hidden fields can potentially have their values edited client-side, however, so it may be worth checking the value again server side, especially if there are any security implications.
Foreign keys can be nullable so just make sure the UserNameId field is not marked with the "[Required]" Data Annotation in your model.
You'll also need to make sure that the column is nullable on the UserStoreName table to match the model otherwise it'll cause problems if your model is different from its underlying table.
Just a small suggestion also, I wouldn't foreign key on strings, I would change your model foreign key to an int, and make sure that the column in the table it's related to is also an int. It's a lot safer to do so, especially if you're dealing with IDENTITY columns.
If there is anything wrong with the reference, an exception will throw when the code tries to save your change, usually because the value it has in the FK reference cannot be found in the related table.

Can Dynamodb save method return haskey?

Currently I have a dynamodb table with hash key marked as DynamoDBAutoGeneratedKey. That means whenever I will save in dynamodb table hashkey will be generated automatically as UUID. I dont need to specify one by myself.
Now I would like to know if there is a way that I can have this hashkey once record is saved in the table. Is there a way that save method returns the record object from which I can get this hashkey?
Thank you,
Prasad
You can get the auto generated id from the model object after the save() method is executed successfully. Please note that DynamoDBMapper class save() method is defined as void. However, it does populate the auto generated id in the model object.
Order id is defined as auto generated key:-
#DynamoDBHashKey(attributeName = "orderId")
#DynamoDBAutoGeneratedKey
public String getOrderId() {
return orderId;
}
Order id is available in the "order" object as soon as the save() method is executed successfully:-
dynamoDBMapper.save(order);
System.out.println("Order id : " + order.getOrderId());
Output:-
Order id : f8b63e5b-eeff-43aa-bcaf-fdc245f43a7c

random EntityValidationErrors (The field is required)

I've been trying to update an Entity using the following code:
var db = new MyContext();
var data = db.Tableau.Find(Id);
if (data != null)
{
data.Name = model.Name;
data.EmbedCode = model.EmbedCode;
db.SaveChanges();
}
The problem is that my Tableaus table has a Parent field (FK not null to a DataTree table). Sometimes when I save the changes to this edited record, I get an error saying that "The Parent field is required". But I am not editing the Parent field. The parent field should be intact and existent, since I am only altering the Name and EmbedCode fields.
How to proceed? Thanks in advance.
That is because you are allowing null values in ParentId column in your Tableaus table, but in your Tableau entity you have ParentId as non-nullable property( which it means the relationship is required), and when you load a Tableau instance from your DB, EF expects that you set that property too. Try changing that property to nullable:
public int? ParentId {get;set;}
If you configure your relationship using Fluent Api it would be:
modelBuilder.Entity<Tableau>()
.HasOptional(t=>t.Parent)
.WithMany(dt=>dt.Tablous)// if you don't have a collection nav. property in your DataTree entity, you can call this method without parameter
.HasForeignKey(t=>t.ParentId);
Update 1
If you want ParentId property as Required in your Tableau entity, you need to make sure that you have a valid value in that column in your DB per each row. With a "valid value" I mean it should be different of the default value and it should exist as PK in your DataTree table.
Update 2:
One way to load a related entity as part of your query is using Include extension method:
var data = db.Tableau.Include(t=>t.Parent).FirstOrDefault(t=>t.Id==Id);

PetaPoco \ NPoco - Partial Insert

Is there a way to partially insert an object using PetaPoco or NPoco?
For example, I have a table called Users:
UserId | UserName | UserMail | UserCreationDate
Each one of these columns are NON NULLABLE and have a default value when they are left empty.
In ASP.NET I have a User class, and I use the ORM to insert a new record with only the name:
Dim userData As New User()
userData.UserName = "Jimmy Hendrix"
db.Insert(userData)
I expect the database to look as follows:
UserId | UserName | UserMail | UserCreationDate
12 | Jimmy Hendrix | (DB default)| (DB default)
I want the insert command only insert the name, without inserting the other object properties with the object's default values.
Such as there is a partial update, I want a partial insert.
Is that possible in PetaPoco?
Is there another way to do it by myself without any ORM?
Edit:
Using SQL I can get the job done, but I need to use POCO objects, so I don't want to have to remember the database parameters. I want something like
user.UserName = "Michael"
user.Insert(user)
And it will insert only the UserName, ignoring the other variables. The SQL that I want to be generated in the background is:
"INSERT Users(UserName) VALUES(#UserName)"
(while the #UserName parameter holds the userData.FirstName value)
As you can see, it doesn't take in account the other variables in the class.
Today if I use the insert command, even if I give a value to a single property in the class, NPoco still tries to insert ALL the class variables into the db setting the variables I didn't want to set with the class's default values (which are different from the db default values)
Also, all of the properties are insertable/updateable, so there can't be any ResultColumn types in the class. I want to insert these values but only the ones I declare in that particular instance. All of the properties are available to update and insert but for each instance i insert only what i declare.
I would create a PartialUserForInsert class:
[TableName("Users")]
public class PartialUserForInsert
{
public string UserName { get; set; }
}
Your provided schema does not include a FirstName column.
Assuming the column is mapped to UserName, using the following should insert as expected.
dim sql = new Sql("INSERT Users(UserName) VALUES(#0)", userData.FirstName)
db.Execute(sql)

stored procedure expects parameter which was not supplied

I'm calling a stored procedure from C# .net and one of the string parameters is null. When that is the case, I pass DBNull.Value. However, I get the above error. Any ideas?
If the string is null, you will see this error. To avoid it, you can set a default parameter value in your stored proc, or you can pass DBNull.Value if your string is null.
You get this if the value of a parameter is "null" (as opposed to DBNull.Value).
Are you sure the parameter value is DBNull.Value?
Do you have access to the Stored Procedure? If so, (And if the Stored procedure logic will allow it), modify the declaration of the input parameter to add " = Null" at the end, as in
Create procedure ProcName
#MyParameterName Integer = Null,
-- con't
As...
Can you give more details like how you are calling the sproc, the parameter itself and the value. You know in your sproc you can set default values for variables.
Something to the effect of:
ALTER SprocMySproc
#myvar varchar(50)=NULL
SELECT blah FROM MyTable WHERE MyField=#myvar OR #myvar IS NULL
Your actual C# or vb.net code can then ignore sending the parameter if it is null or empty
if(!(String.IsNullOrEmpty(myVar)))
{
//pass the parameter
mySQLCommandObject.Parameters.Add("#myvar", sqldbtype.varchar).Value = myVar;
//other code...
}

Resources