Closed MrFoxPro closed 4 years ago
I think function should return res.Data[0].ToObject<T>();
, not the (T)(object)res.Data[0];
So complicated. I tried to repeat this code with boxing/unboxing, converting to jobject and back. But ids equals anyway.
Oh. Seems like i understood wrong this function... Insert method wouldn't return object. But why i get default(T)?
Hi Dmitriy,
You need to use .RunWrite(conn)
instead. Please be confident that you see a problem in the driver source code before posting a GitHub issue for help. Supposing a problem exists is not sufficient for posting issues. If you think you might need help, please use the public help Slack and Discord channels.
The code in the driver that you referenced above is correct.
The only time (T)(object)res.Data[0];
is called is if T
is typeof(T).IsJToken()
; and in this case, T
is State
not a JObject
/JArray
/JValue
/JToken
.
Because T
is State
the code res.Data[0].ToObject<T>(Converter.Serializer);
is executed as expected.
The reason you are receiving an empty State
object that looks like default(T)
is that you're deserializing JSON response data with the wrong type of T
.
For example, this is what you're doing:
public class ServerWriteResponse{
public int Inserted {get;set;}
public int Deleted {get;set;}
}
public class State{
public string SomeProperty {get;set;}
public string Id {get;set;}
}
The response from for the table.Insert(state)
is:
{
"inserted": 1,
"deleted": 0
}
Effectively, when you specify .RunAtom<State>(conn)
you are saying to the driver the following:
JsonConvert.Deseralize<State>("{'inserted':1,'deleted':0}").Id != state.Id
The code above does not make any sense because the JSON insert response does not match State
type. This is why you get an object that looks like default(T)
. The JSON data does not match the type T
specified.
The correct usage is as follows:
[TestFixture]
public class Issue147
{
public class State
{
[JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Id { get; set; }
public string someProperty { get; set; }
protected internal State()
{
this.Id = Guid.NewGuid().ToString();
}
[JsonConstructor]
public State(string someProperty)
{
}
}
[Test]
public void Test()
{
var conn = R.Connection().Connect();
var s = new State();
var table = R.Db("query").Table("test");
var result = table.Insert(s).RunWrite(conn);
result.Inserted.Should().Be(1);
}
}
Please remember, if you don't have 100% confidence there is an issue with driver code, please ask for help in the chat channels. I will try to answer any questions you have when I have time.
Thanks, Brian Chavez
Version Information
What is the expected behavior?
Following client-side primary key generation guide, we should use non-public constructor to implement id generation. This is best way, but Insert().RunAtom() returns a object with regenerated uuid, even if another ctor with another public ctor with JsonConstructor attribute is defined.
What is the actual behavior?
Object should be generated without calling a constructor (idk, may it should be in config)?
Any possible solutions?
no
How do you reproduce the issue?
Do you have a unit test that can demonstrate the bug?
no.
Can you identify the location in the driver source code where the problem exists?
I suppose: Connection.cs, line 300-305
If the bug is confirmed, would you be willing to submit a PR?
Yes
Sorry for my English.