diff --git a/examples/EdgeDB.Examples.ExampleTODOApi/EdgeDB.Examples.ExampleTODOApi.csproj b/examples/EdgeDB.Examples.ExampleTODOApi/EdgeDB.Examples.ExampleTODOApi.csproj
index e9337af1..b085b0bf 100644
--- a/examples/EdgeDB.Examples.ExampleTODOApi/EdgeDB.Examples.ExampleTODOApi.csproj
+++ b/examples/EdgeDB.Examples.ExampleTODOApi/EdgeDB.Examples.ExampleTODOApi.csproj
@@ -7,11 +7,11 @@
-
+
-
+
diff --git a/examples/EdgeDB.Examples.ExampleTODOApi/README.md b/examples/EdgeDB.Examples.ExampleTODOApi/README.md
index f9e5ea15..2937e1cd 100644
--- a/examples/EdgeDB.Examples.ExampleTODOApi/README.md
+++ b/examples/EdgeDB.Examples.ExampleTODOApi/README.md
@@ -1,6 +1,7 @@
# Building a TODO API with EdgeDB and ASP.Net Core
-For this tutorial we're going to build a simple TODO API using the EdgeDB as a database. We'll start by creating a new asp.net core project.
+For this tutorial we're going to build a simple TODO API using the EdgeDB as a database. We'll start by creating a new
+asp.net core project.
```console
$ dotnet new webapi -n EdgeDB.Examples.ExampleTODOApi
@@ -8,13 +9,14 @@ $ dotnet new webapi -n EdgeDB.Examples.ExampleTODOApi
Once we have our ASP.Net Core project, we can add the EdgeDB.Net driver to our project as a reference.
-
#### Myget
+
```console
$ dotnet add package EdgeDB.Net.Driver -Source https://www.myget.org/F/edgedb-net/api/v3/index.json
```
#### NuGet
+
```console
$ dotnet add package EdgeDB.Net.Driver
```
@@ -26,18 +28,22 @@ Lets now create our EdgeDB instance for this API, for this we're going to use th
### Installing the CLI
#### Linux or macOS
+
```console
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
```
#### Windows Powershell
+
```ps
PS> iwr https://ps1.edgedb.com -useb | iex
```
-Then verify that the CLI is installed and available with the `edgedb --version` command. If you get a `Command not found` error, you may need to open a new terminal window before the `edgedb` command is available.
+Then verify that the CLI is installed and available with the `edgedb --version` command. If you get
+a `Command not found` error, you may need to open a new terminal window before the `edgedb` command is available.
-Once the CLI is installed, we can initialize a project for our TODO api. You can read more about [EdgeDB projects here.](https://www.edgedb.com/docs/guides/projects)
+Once the CLI is installed, we can initialize a project for our TODO api. You can read more
+about [EdgeDB projects here.](https://www.edgedb.com/docs/guides/projects)
```console
$ edgedb project init
@@ -78,7 +84,10 @@ Project initialized.
## Defining the schema
-We now have a edgedb project linked to our TODO API, lets next add our schema we will use for our API. Our database schema file is located in the `dbschema` directory, by default the name of the file is `default.esdl` and it looks like this
+We now have a edgedb project linked to our TODO API, lets next add our schema we will use for our API. Our database
+schema file is located in the `dbschema` directory, by default the name of the file is `default.esdl` and it looks like
+this
+
```d
module default {
@@ -86,6 +95,7 @@ module default {
```
Lets add a type called `TODO`
+
```diff
module default {
+ type TODO {
@@ -94,7 +104,9 @@ module default {
}
```
-Our todo structure will consist of four feilds: `title`, `description`, `date_created`, and `state`. Our `state` field will be the state of the todo ex: `Not Started`, `In Progress`, `Completed`, for this we will have to define our own enum type. You can read more about [enums here.](https://www.edgedb.com/docs/datamodel/primitives#enums).
+Our todo structure will consist of four feilds: `title`, `description`, `date_created`, and `state`. Our `state` field
+will be the state of the todo ex: `Not Started`, `In Progress`, `Completed`, for this we will have to define our own
+enum type. You can read more about [enums here.](https://www.edgedb.com/docs/datamodel/primitives#enums).
```diff
module default {
@@ -108,7 +120,7 @@ module default {
Lets now finally add our properties to our type.
-```diff
+```diff
module default {
scalar type State extending enum;
@@ -126,13 +138,15 @@ module default {
Our datetime property will automatically be set to the current date and time when the todo is created.
Lets now run the migration commands to apply the schema change to the database.
+
```console
$ edgedb migration create
```
## Defining our C# type
-Lets now define our C# type that will represent the `TODO` type in the schema file. We can do this with a simple class like so:
+Lets now define our C# type that will represent the `TODO` type in the schema file. We can do this with a simple class
+like so:
```cs
public class TODOModel
@@ -156,6 +170,7 @@ public class TODOModel
}
}
```
+
We now need to mark this type as a valid type to use when deserializing, we can do this with the `EdgeDbType` attribute
```diff
@@ -163,7 +178,8 @@ We now need to mark this type as a valid type to use when deserializing, we can
public class TODOModel
```
-One thing to note is our property names, they're different from the ones in the schema file. We can use the `EdgeDBProperty` attribute to map the schema file property names to the C# properties.
+One thing to note is our property names, they're different from the ones in the schema file. We can use
+the `EdgeDBProperty` attribute to map the schema file property names to the C# properties.
```diff
public class TODOModel
@@ -225,12 +241,13 @@ We should also add attributes for serializing this class to JSON as we're going
Our type is now mapped to the edgedb type `TODO` and we can use it to deserialize query data.
-
## Setting up EdgeDB.Net in our project
-Lets now setup an edgedb client we can use for our project, this is relatively simple for us as we can use [Dependency Injection](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-6.0).
+Lets now setup an edgedb client we can use for our project, this is relatively simple for us as we can
+use [Dependency Injection](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-6.0).
Lets head over to our `Program.cs` file and add the following:
+
```diff
+ using EdgeDB;
@@ -267,7 +284,8 @@ And thats it! We now have a `EdgeDBClient` singleton within our service collecti
## Defining our API routes
-Lets create a new controller for our API called `TODOController` and have DI inject the `EdgeDBClient` into the constructor.
+Lets create a new controller for our API called `TODOController` and have DI inject the `EdgeDBClient` into the
+constructor.
```diff
+using Microsoft.AspNetCore.Mvc;
@@ -284,7 +302,7 @@ Lets create a new controller for our API called `TODOController` and have DI inj
+ _client = client;
+ }
+ }
-+}
++}
```
Lets start with the `GET` route for fetching all of our todos.
@@ -312,16 +330,21 @@ namespace EdgeDB.Examples.ExampleTODOApi.Controllers
+ return Ok(todos);
+ }
}
-}
+}
```
-We use the `QueryAsync` method on the client as our query will return 0 or many results, we also pass in our `TODOModel` class from earlier to deserialize the results as that class. Finally, we return out the collection of todos as a JSON response.
+We use the `QueryAsync` method on the client as our query will return 0 or many results, we also pass in
+our `TODOModel` class from earlier to deserialize the results as that class. Finally, we return out the collection of
+todos as a JSON response.
### Testing the GET route
-We can test the route with the [swagger interface](https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-6.0&tabs=visual-studio) by running our project and then clicking on the `GET /todos` route.
+We can test the route with
+the [swagger interface](https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-6.0&tabs=visual-studio)
+by running our project and then clicking on the `GET /todos` route.
We can see the return result of our `GET` route is a 200 with an empty JSON array:
+
```json
GET /todos
@@ -371,15 +394,17 @@ namespace EdgeDB.Examples.ExampleTODOApi.Controllers
+ return NoContent();
+ }
}
-}
+}
```
-Our new route will validate the todo we're passing in and if it's valid, we'll insert it into the database. One thing to note here is we're using the `Dictionary` to pass in our parameters. This is to prevent any query injection attacks. You can learn more about [EdgeQL parameters here.](https://www.edgedb.com/docs/edgeql/parameters).
-
+Our new route will validate the todo we're passing in and if it's valid, we'll insert it into the database. One thing to
+note here is we're using the `Dictionary` to pass in our parameters. This is to prevent any query
+injection attacks. You can learn more about [EdgeQL parameters here.](https://www.edgedb.com/docs/edgeql/parameters).
### Testing the POST route
Using the Swagger UI, we will run our route with this post body
+
```json
POST /todos
@@ -389,9 +414,11 @@ POST /todos
"state": 0
}
```
+
We don't include the date as that property is generated by the database, and should not be controlled by the user.
We get a 204 meaning our route was successful, lets now call the `GET` route to see our newly created todo:
+
```json
GET /todos
@@ -405,7 +432,8 @@ GET /todos
]
```
-Here we can see our todo was created successfully as well as returned from our api successfully. Lets next add a route to delete todos.
+Here we can see our todo was created successfully as well as returned from our api successfully. Lets next add a route
+to delete todos.
```diff
using Microsoft.AspNetCore.Mvc;
@@ -452,23 +480,28 @@ namespace EdgeDB.Examples.ExampleTODOApi.Controllers
+ public async Task DeleteTODO([FromQuery, Required]string title)
+ {
+ var result = await _client.QueryAsync("delete TODO filter .title = $title", new Dictionary { { "title", title } });
-+
++
+ return result.Count > 0 ? NoContent() : NotFound();
+ }
}
-}
+}
```
-Our delete route will take in a title as a query parameter and delete the todo with that title. Note that we're using the `QueryAsync` method here with an `object` as the return type so we can count how many todos were deleted, then returning 204 if we deleted at least one todo, and 404 if we didn't.
+Our delete route will take in a title as a query parameter and delete the todo with that title. Note that we're using
+the `QueryAsync` method here with an `object` as the return type so we can count how many todos were deleted, then
+returning 204 if we deleted at least one todo, and 404 if we didn't.
## Testing the DELETE route
Using the Swagger UI, we will run our route with this query parameter
+
```
?title=Hello
```
-Once we execute this we see we got a 204 meaning our route was successful, lets now call the `GET` route to see if our todo still exists.
+Once we execute this we see we got a 204 meaning our route was successful, lets now call the `GET` route to see if our
+todo still exists.
+
```json
GET /todos
@@ -524,29 +557,30 @@ namespace EdgeDB.Examples.ExampleTODOApi.Controllers
public async Task DeleteTODO([FromQuery, Required]string title)
{
var result = await _client.QueryAsync("delete TODO filter .title = $title", new Dictionary { { "title", title } });
-
+
return result.Count > 0 ? NoContent() : NotFound();
}
+ [HttpPatch("/todos")]
+ public async Task UpdateTODO([FromQuery, Required] string title, [FromQuery, Required]TODOState state)
+ {
-+ var result = await _client.QueryAsync("update TODO filter .title = $title set { state := $state }", new Dictionary
-+ {
++ var result = await _client.QueryAsync("update TODO filter .title = $title set { state := $state }", new Dictionary
++ {
+ { "title", title } ,
+ { "state", state }
+ });
+ return result.Count > 0 ? NoContent() : NotFound();
+ }
}
-}
+}
```
This route will take in a title and a state as query parameters and update the todo with that title to the given state.
## Testing the PATCH route
-Lets run the same `POST` request we did earlier to create another todo, then lets call `PATCH` to update the state of our todo.
+Lets run the same `POST` request we did earlier to create another todo, then lets call `PATCH` to update the state of
+our todo.
```
PATCH /todos
@@ -554,7 +588,9 @@ PATCH /todos
?title=Hello$state=1
```
-Running this we get a 204 meaning our route was successful, lets now call the `GET` route to see our todo and check if its state was updated
+Running this we get a 204 meaning our route was successful, lets now call the `GET` route to see our todo and check if
+its state was updated
+
```json
GET /todos
@@ -572,4 +608,6 @@ As we can see our state was updated successfully.
# Conclusion
-This tutorial has covered the basics of how to use the EdgeDB client to query, update and delete data. Feel free to expirement with the source code [here](https://github.com/quinchs/EdgeDB.Net/tree/dev/examples/EdgeDB.Examples.ExampleTODOApi).
\ No newline at end of file
+This tutorial has covered the basics of how to use the EdgeDB client to query, update and delete data. Feel free to
+expirement with the source
+code [here](https://github.com/quinchs/EdgeDB.Net/tree/dev/examples/EdgeDB.Examples.ExampleTODOApi).
diff --git a/src/EdgeDB.Net.Driver/Binary/Builders/Info/EdgeDBTypeDeserializerInfo.cs b/src/EdgeDB.Net.Driver/Binary/Builders/Info/EdgeDBTypeDeserializerInfo.cs
index b4fedd9b..dd3d4189 100644
--- a/src/EdgeDB.Net.Driver/Binary/Builders/Info/EdgeDBTypeDeserializerInfo.cs
+++ b/src/EdgeDB.Net.Driver/Binary/Builders/Info/EdgeDBTypeDeserializerInfo.cs
@@ -1,341 +1,332 @@
-using EdgeDB.Binary;
using EdgeDB.Binary.Builders.Wrappers;
using EdgeDB.DataTypes;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
-namespace EdgeDB
-{
- internal sealed class EdgeDBTypeDeserializeInfo
- {
- public string EdgeDBTypeName { get; }
+namespace EdgeDB;
- public bool IsAbtractType
- => _type.IsAbstract || _type.IsInterface;
+internal sealed class EdgeDBTypeDeserializeInfo
+{
+ private readonly Type _type;
+ private EdgeDBTypeConstructorInfo? _ctorInfo;
- public bool RequiresTypeName { get; private set; }
+ private EdgeDBPropertyMapInfo? _propertyMapInfo;
- public TypeDeserializerFactory Factory => _factory;
+ private ObjectActivator? _typeActivator;
- public Dictionary Children { get; } = new();
+ private readonly IWrapper? _wrapper;
- internal EdgeDBPropertyInfo[] Properties
- => PropertyMapInfo.Properties;
+ public EdgeDBTypeDeserializeInfo(Type type)
+ {
+ IWrapper.TryGetWrapper(type, out _wrapper);
- internal EdgeDBPropertyMapInfo PropertyMapInfo
- => _propertyMapInfo ??= EdgeDBPropertyMapInfo.Create(_type);
+ _type = _wrapper?.GetInnerType(type) ?? type;
- internal EdgeDBTypeConstructorInfo? ConstructorInfo
- => _ctorInfo ??= (EdgeDBTypeConstructorInfo.TryGetConstructorInfo(_type, PropertyMapInfo, out var ctorInfo) ? ctorInfo : null);
+ var factory = CreateDefaultFactory();
- private ObjectActivator? Activator
- => _typeActivator ??= CreateActivator();
+ EdgeDBTypeName = _type.GetCustomAttribute()?.Name ?? _type.Name;
- private readonly Type _type;
+ if (_wrapper is not null)
+ {
+ Factory = (ref ObjectEnumerator enumerator) =>
+ {
+ var value = factory(ref enumerator);
+ return _wrapper.Wrap(type, value);
+ };
+ }
+ else
+ {
+ Factory = factory;
+ }
+ }
- private ObjectActivator? _typeActivator;
- private EdgeDBTypeConstructorInfo? _ctorInfo;
- private EdgeDBPropertyMapInfo? _propertyMapInfo;
+ public EdgeDBTypeDeserializeInfo(Type type, TypeDeserializerFactory factory)
+ {
+ IWrapper.TryGetWrapper(type, out _wrapper);
- private TypeDeserializerFactory _factory;
+ _type = _wrapper?.GetInnerType(type) ?? type;
- private IWrapper? _wrapper;
+ EdgeDBTypeName = _type.GetCustomAttribute()?.Name ?? _type.Name;
- public EdgeDBTypeDeserializeInfo(Type type)
+ if (_wrapper is not null)
+ {
+ Factory = (ref ObjectEnumerator enumerator) =>
+ {
+ var value = factory(ref enumerator);
+ return _wrapper.Wrap(type, value);
+ };
+ }
+ else
{
- IWrapper.TryGetWrapper(type, out _wrapper);
+ Factory = factory;
+ }
+ }
- _type = _wrapper?.GetInnerType(type) ?? type;
+ public string EdgeDBTypeName { get; }
- var factory = CreateDefaultFactory();
+ public bool IsAbtractType
+ => _type.IsAbstract || _type.IsInterface;
- EdgeDBTypeName = _type.GetCustomAttribute()?.Name ?? _type.Name;
+ public bool RequiresTypeName { get; private set; }
- if(_wrapper is not null)
- {
- _factory = (ref ObjectEnumerator enumerator) =>
- {
- var value = factory(ref enumerator);
- return _wrapper.Wrap(type, value);
- };
- }
- else
- {
- _factory = factory;
- }
- }
+ public TypeDeserializerFactory Factory { get; private set; }
- public EdgeDBTypeDeserializeInfo(Type type, TypeDeserializerFactory factory)
- {
- IWrapper.TryGetWrapper(type, out _wrapper);
+ public Dictionary Children { get; } = new();
- _type = _wrapper?.GetInnerType(type) ?? type;
+ internal EdgeDBPropertyInfo[] Properties
+ => PropertyMapInfo.Properties;
- EdgeDBTypeName = _type.GetCustomAttribute()?.Name ?? _type.Name;
+ internal EdgeDBPropertyMapInfo PropertyMapInfo
+ => _propertyMapInfo ??= EdgeDBPropertyMapInfo.Create(_type);
- if (_wrapper is not null)
- {
- _factory = (ref ObjectEnumerator enumerator) =>
- {
- var value = factory(ref enumerator);
- return _wrapper.Wrap(type, value);
- };
- }
- else
- {
- _factory = factory;
- }
- }
+ internal EdgeDBTypeConstructorInfo? ConstructorInfo
+ => _ctorInfo ??= EdgeDBTypeConstructorInfo.TryGetConstructorInfo(_type, PropertyMapInfo, out var ctorInfo)
+ ? ctorInfo
+ : null;
- private ObjectActivator? CreateActivator()
- {
- if (IsAbtractType)
- return null;
+ private ObjectActivator? Activator
+ => _typeActivator ??= CreateActivator();
- if (!ConstructorInfo.HasValue || ConstructorInfo.Value.EmptyConstructor is null)
- return null;
+ private ObjectActivator? CreateActivator()
+ {
+ if (IsAbtractType)
+ return null;
- Expression newExp = Expression.New(ConstructorInfo.Value.EmptyConstructor);
+ if (!ConstructorInfo.HasValue || ConstructorInfo.Value.EmptyConstructor is null)
+ return null;
- if (_type.IsValueType)
- newExp = Expression.TypeAs(newExp, typeof(object));
+ Expression newExp = Expression.New(ConstructorInfo.Value.EmptyConstructor);
- return Expression.Lambda(newExp).Compile();
- }
+ if (_type.IsValueType)
+ newExp = Expression.TypeAs(newExp, typeof(object));
- public void AddOrUpdateChildren(EdgeDBTypeDeserializeInfo child)
- => Children[child._type] = child;
+ return Expression.Lambda(newExp).Compile();
+ }
- public void AddOrUpdateChildren(IEnumerable children)
- {
- foreach (var child in children)
- AddOrUpdateChildren(child);
- }
+ public void AddOrUpdateChildren(EdgeDBTypeDeserializeInfo child)
+ => Children[child._type] = child;
- public void UpdateFactory(TypeDeserializerFactory factory)
- {
- _factory = factory;
- }
+ public void AddOrUpdateChildren(IEnumerable children)
+ {
+ foreach (var child in children)
+ AddOrUpdateChildren(child);
+ }
- private bool CanDeserializeToTuple()
- {
- return _type == typeof(TransientTuple) ||
- TransientTuple.IsValueTupleType(_type) ||
- TransientTuple.IsReferenceTupleType(_type);
- }
+ public void UpdateFactory(TypeDeserializerFactory factory) => Factory = factory;
- private TypeDeserializerFactory CreateDefaultFactory()
- {
- if (_type == typeof(object))
- return (ref ObjectEnumerator enumerator) => enumerator.ToDynamic();
+ private bool CanDeserializeToTuple() =>
+ _type == typeof(TransientTuple) ||
+ TransientTuple.IsValueTupleType(_type) ||
+ TransientTuple.IsReferenceTupleType(_type);
- if (_type.IsAssignableFrom(typeof(Dictionary)))
- return (ref ObjectEnumerator enumerator) => new Dictionary(
- (IDictionary)enumerator.ToDynamic()!
- );
+ private TypeDeserializerFactory CreateDefaultFactory()
+ {
+ if (_type == typeof(object))
+ return (ref ObjectEnumerator enumerator) => enumerator.ToDynamic();
- // is it a tuple
- if (_type.IsAssignableTo(typeof(ITuple)) && CanDeserializeToTuple())
- {
- return (ref ObjectEnumerator enumerator) =>
- {
- var transient = TransientTuple.FromObjectEnumerator(ref enumerator);
-
- if (_type == typeof(TransientTuple))
- return transient;
- else if (TransientTuple.IsValueTupleType(_type))
- return transient.ToValueTuple();
- else if (TransientTuple.IsReferenceTupleType(_type))
- return transient.ToReferenceTuple();
- else
- throw new NoTypeConverterException($"Cannot convert transient tuple to {_type.Name}");
- };
- }
+ if (_type.IsAssignableFrom(typeof(Dictionary)))
+ return (ref ObjectEnumerator enumerator) => new Dictionary(
+ (IDictionary)enumerator.ToDynamic()!
+ );
- // proxy type
- var proxyAttr = _type.GetCustomAttribute();
- if (proxyAttr is not null)
+ // is it a tuple
+ if (_type.IsAssignableTo(typeof(ITuple)) && CanDeserializeToTuple())
+ {
+ return (ref ObjectEnumerator enumerator) =>
{
- var targetType = proxyAttr.Target;
+ var transient = TransientTuple.FromObjectEnumerator(ref enumerator);
+
+ if (_type == typeof(TransientTuple))
+ return transient;
+ if (TransientTuple.IsValueTupleType(_type))
+ return transient.ToValueTuple();
+ if (TransientTuple.IsReferenceTupleType(_type))
+ return transient.ToReferenceTuple();
+ throw new NoTypeConverterException($"Cannot convert transient tuple to {_type.Name}");
+ };
+ }
- // proxy should only have one constructor
- var ctors = _type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
+ // proxy type
+ var proxyAttr = _type.GetCustomAttribute();
+ if (proxyAttr is not null)
+ {
+ var targetType = proxyAttr.Target;
- if (ctors.Length is not 1)
- throw new InvalidOperationException($"Proxy type {_type} does not have a valid constructor");
+ // proxy should only have one constructor
+ var ctors = _type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
- var ctor = ctors[0];
- var ctorParams = ctor.GetParameters();
+ if (ctors.Length is not 1)
+ throw new InvalidOperationException($"Proxy type {_type} does not have a valid constructor");
- if (ctorParams.Length is > 1 or < 0)
- throw new InvalidOperationException($"Proxy type {_type} does not have a valid constructor that takes one argument");
+ var ctor = ctors[0];
+ var ctorParams = ctor.GetParameters();
- targetType ??= ctor.GetParameters()[0].ParameterType;
+ if (ctorParams.Length is > 1 or < 0)
+ throw new InvalidOperationException(
+ $"Proxy type {_type} does not have a valid constructor that takes one argument");
- // return the proxied types factory
- var proxiedFactory = TypeBuilder.GetDeserializationFactory(targetType);
+ targetType ??= ctor.GetParameters()[0].ParameterType;
- return (ref ObjectEnumerator enumerator) =>
- {
- var proxiedValue = proxiedFactory(ref enumerator);
- return ctor.Invoke(new[] { proxiedValue });
- };
- }
+ // return the proxied types factory
+ var proxiedFactory = TypeBuilder.GetDeserializationFactory(targetType);
- // if type has custom method builder
- if (_type.TryGetCustomBuilder(out var methodInfo))
+ return (ref ObjectEnumerator enumerator) =>
{
- return (ref ObjectEnumerator enumerator) =>
- {
- var instance = CreateInstance();
+ var proxiedValue = proxiedFactory(ref enumerator);
+ return ctor.Invoke(new[] {proxiedValue});
+ };
+ }
+
+ // if type has custom method builder
+ if (_type.TryGetCustomBuilder(out var methodInfo))
+ {
+ return (ref ObjectEnumerator enumerator) =>
+ {
+ var instance = CreateInstance();
- if (instance is null)
- throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null);
+ if (instance is null)
+ throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null);
- methodInfo!.Invoke(instance, new object?[] { enumerator.ToDynamic() });
+ methodInfo!.Invoke(instance, new object?[] {enumerator.ToDynamic()});
- return instance;
- };
- }
+ return instance;
+ };
+ }
- // if type has custom constructor factory
- if (ConstructorInfo.HasValue && ConstructorInfo.Value.Constructor is not null)
- {
- var ctor = ConstructorInfo.Value.Constructor;
+ // if type has custom constructor factory
+ if (ConstructorInfo.HasValue && ConstructorInfo.Value.Constructor is not null)
+ {
+ var ctor = ConstructorInfo.Value.Constructor;
- switch (ConstructorInfo.Value.ParamType)
- {
- case EdgeDBConstructorParamType.Dynamic:
- return (ref ObjectEnumerator enumerator) =>
- {
- return ctor.Invoke(new object?[] { enumerator.ToDynamic() });
- };
- case EdgeDBConstructorParamType.Dictionary:
- return (ref ObjectEnumerator enumerator) =>
- {
- return ctor.Invoke(new object?[] { enumerator.Flatten() });
- };
- case EdgeDBConstructorParamType.ObjectEnumerator:
- return (ref ObjectEnumerator enumerator) =>
- {
- var lambda = Expression.Lambda(
- Expression.New(ctor, Expression.Parameter(typeof(ObjectEnumerator), "enumerator")),
- Expression.Parameter(typeof(ObjectEnumerator), "enumerator")
- ).Compile();
-
- return lambda(enumerator);
- };
- case EdgeDBConstructorParamType.RefObjectEnumerator:
- return Expression.Lambda(
- Expression.New(ctor, Expression.Parameter(ObjectEnumerator.RefType, "enumerator")),
- Expression.Parameter(ObjectEnumerator.RefType, "enumerator")
+ switch (ConstructorInfo.Value.ParamType)
+ {
+ case EdgeDBConstructorParamType.Dynamic:
+ return (ref ObjectEnumerator enumerator) =>
+ {
+ return ctor.Invoke(new object?[] {enumerator.ToDynamic()});
+ };
+ case EdgeDBConstructorParamType.Dictionary:
+ return (ref ObjectEnumerator enumerator) =>
+ {
+ return ctor.Invoke(new object?[] {enumerator.Flatten()});
+ };
+ case EdgeDBConstructorParamType.ObjectEnumerator:
+ return (ref ObjectEnumerator enumerator) =>
+ {
+ var lambda = Expression.Lambda(
+ Expression.New(ctor, Expression.Parameter(typeof(ObjectEnumerator), "enumerator")),
+ Expression.Parameter(typeof(ObjectEnumerator), "enumerator")
).Compile();
- case EdgeDBConstructorParamType.Props:
- return (ref ObjectEnumerator enumerator) =>
- {
- var ctorParams = new object?[Properties.Length];
- var reverseIndexer = new FastInverseIndexer(Properties.Length);
- while (enumerator.Next(out var name, out var value))
+ return lambda(enumerator);
+ };
+ case EdgeDBConstructorParamType.RefObjectEnumerator:
+ return Expression.Lambda(
+ Expression.New(ctor, Expression.Parameter(ObjectEnumerator.RefType, "enumerator")),
+ Expression.Parameter(ObjectEnumerator.RefType, "enumerator")
+ ).Compile();
+ case EdgeDBConstructorParamType.Props:
+ return (ref ObjectEnumerator enumerator) =>
+ {
+ var ctorParams = new object?[Properties.Length];
+ var reverseIndexer = new FastInverseIndexer(Properties.Length);
+
+ while (enumerator.Next(out var name, out var value))
+ {
+ if (PropertyMapInfo.Map.TryGetValue(name, out var prop))
{
- if (PropertyMapInfo.Map.TryGetValue(name, out var prop))
+ var index = PropertyMapInfo.IndexMap[prop];
+ reverseIndexer.Track(index);
+
+ try
+ {
+ ctorParams[index] = prop.ConvertToPropertyType(value);
+ }
+ catch (Exception x)
{
- var index = PropertyMapInfo.IndexMap[prop];
- reverseIndexer.Track(index);
-
- try
- {
- ctorParams[index] = prop.ConvertToPropertyType(value);
- }
- catch (Exception x)
- {
- throw new NoTypeConverterException($"Cannot assign property {prop.PropertyName} with type {value?.GetType().Name ?? "unknown"}", x);
- }
+ throw new NoTypeConverterException(
+ $"Cannot assign property {prop.PropertyName} with type {value?.GetType().Name ?? "unknown"}",
+ x);
}
}
+ }
- // fill the missed properties with defaults
- var missed = reverseIndexer.GetIndexies();
- for (int i = 0; i != missed.Length; i++)
- {
- var prop = Properties[missed[i]];
- ctorParams[missed[i]] = ReflectionUtils.GetDefault(prop.Type);
- }
+ // fill the missed properties with defaults
+ var missed = reverseIndexer.GetIndexies();
+ for (var i = 0; i != missed.Length; i++)
+ {
+ var prop = Properties[missed[i]];
+ ctorParams[missed[i]] = ReflectionUtils.GetDefault(prop.Type);
+ }
- return ctor.Invoke(ctorParams);
- };
- }
+ return ctor.Invoke(ctorParams);
+ };
}
+ }
- // is it abstract
- if (IsAbtractType)
- {
- RequiresTypeName = true;
-
- return (ref ObjectEnumerator enumerator) =>
- {
- // introspect the type name
- if (!enumerator.Next(out var name, out var value) || name != "__tname__")
- throw new ConfigurationException("Type introspection is required for abstract types, this is a bug.");
-
- var typeName = (string)value!;
-
- // remove the modulename
- typeName = typeName.Split("::").Last();
-
- EdgeDBTypeDeserializeInfo? info = null;
-
- if ((info = Children.FirstOrDefault(x => x.Value.EdgeDBTypeName == typeName).Value) is null)
- {
- throw new EdgeDBException($"Failed to deserialize the edgedb type '{typeName}'. Could not find relivant child of {_type.Name}");
- }
-
- // deserialize as child
- return info.Deserialize(ref enumerator);
- };
- }
+ // is it abstract
+ if (IsAbtractType)
+ {
+ RequiresTypeName = true;
return (ref ObjectEnumerator enumerator) =>
{
- var instance = CreateInstance();
+ // introspect the type name
+ if (!enumerator.Next(out var name, out var value) || name != "__tname__")
+ throw new ConfigurationException(
+ "Type introspection is required for abstract types, this is a bug.");
- if (instance is null)
- throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null);
+ var typeName = (string)value!;
- while (enumerator.Next(out var name, out var value))
- {
- if (!PropertyMapInfo.Map.TryGetValue(name, out var prop))
- continue;
+ // remove the modulename
+ typeName = typeName.Split("::").Last();
- prop.ConvertAndSetValue(instance, value);
+ EdgeDBTypeDeserializeInfo? info = null;
+
+ if ((info = Children.FirstOrDefault(x => x.Value.EdgeDBTypeName == typeName).Value) is null)
+ {
+ throw new EdgeDBException(
+ $"Failed to deserialize the edgedb type '{typeName}'. Could not find relivant child of {_type.Name}");
}
- return instance;
+ // deserialize as child
+ return info.Deserialize(ref enumerator);
};
}
- private object CreateInstance()
+ return (ref ObjectEnumerator enumerator) =>
{
- if (Activator is null)
- throw new InvalidOperationException($"No empty constructor found on type {_type}");
+ var instance = CreateInstance();
- return Activator();
- }
+ if (instance is null)
+ throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null);
- public object? Deserialize(ref ObjectEnumerator enumerator)
- => _factory(ref enumerator);
+ while (enumerator.Next(out var name, out var value))
+ {
+ if (!PropertyMapInfo.Map.TryGetValue(name, out var prop))
+ continue;
- private delegate object ObjectActivator();
+ prop.ConvertAndSetValue(instance, value);
+ }
- public static implicit operator TypeDeserializerFactory(EdgeDBTypeDeserializeInfo info) => info._factory;
+ return instance;
+ };
}
+
+ private object CreateInstance()
+ {
+ if (Activator is null)
+ throw new InvalidOperationException($"No empty constructor found on type {_type}");
+
+ return Activator();
+ }
+
+ public object? Deserialize(ref ObjectEnumerator enumerator)
+ => Factory(ref enumerator);
+
+ public static implicit operator TypeDeserializerFactory(EdgeDBTypeDeserializeInfo info) => info.Factory;
+
+ private delegate object ObjectActivator();
}
diff --git a/src/EdgeDB.Net.Driver/Transaction.cs b/src/EdgeDB.Net.Driver/Transaction.cs
index 102abe1f..a95bc0f3 100644
--- a/src/EdgeDB.Net.Driver/Transaction.cs
+++ b/src/EdgeDB.Net.Driver/Transaction.cs
@@ -1,161 +1,164 @@
using EdgeDB.DataTypes;
-namespace EdgeDB
+namespace EdgeDB;
+
+///
+/// Represents a transaction within EdgeDB.
+///
+public sealed class Transaction : IEdgeDBQueryable
{
+ private readonly ITransactibleClient _client;
+ private readonly object _lock = new();
+ private readonly TransactionSettings _settings;
+
+ internal Transaction(ITransactibleClient client, TransactionSettings settings)
+ {
+ _client = client;
+ _settings = settings;
+ }
+
///
- /// Represents a transaction within EdgeDB.
+ /// Gets the transaction state of this transaction.
///
- public sealed class Transaction : IEdgeDBQueryable
- {
- ///
- /// Gets the transaction state of this transaction.
- ///
- public TransactionState State
- => _client.TransactionState;
+ public TransactionState State
+ => _client.TransactionState;
- private readonly ITransactibleClient _client;
- private readonly TransactionSettings _settings;
- private readonly object _lock = new();
+ ///
+ public Task ExecuteAsync(string query, IDictionary? args = null,
+ Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
+ => ExecuteInternalAsync(() => _client.ExecuteAsync(query, args, capabilities, token));
- internal Transaction(ITransactibleClient client, TransactionSettings settings)
- {
- _client = client;
- _settings = settings;
- }
+ ///
+ public Task> QueryAsync(string query,
+ IDictionary? args = null,
+ Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
+ => ExecuteInternalAsync(() => _client.QueryAsync(query, args, capabilities, token));
+
+ ///
+ public Task QuerySingleAsync(string query, IDictionary? args = null,
+ Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
+ => ExecuteInternalAsync(() => _client.QuerySingleAsync(query, args, capabilities, token));
+
+ ///
+ public Task QueryRequiredSingleAsync(string query, IDictionary? args = null,
+ Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
+ => ExecuteInternalAsync(() => _client.QueryRequiredSingleAsync(query, args, capabilities, token));
+
+ public Task QueryJsonAsync(string query, IDictionary? args = null,
+ Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
+ => ExecuteInternalAsync(() => _client.QueryJsonAsync(query, args, capabilities, token));
- internal Task StartAsync()
- => _client.StartTransactionAsync(_settings.Isolation, _settings.ReadOnly, _settings.Deferrable);
+ public Task> QueryJsonElementsAsync(string query,
+ IDictionary? args = null,
+ Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
+ => ExecuteInternalAsync(() => _client.QueryJsonElementsAsync(query, args, capabilities, token));
- internal Task CommitAsync()
- => _client.CommitAsync();
+ internal Task StartAsync()
+ => _client.StartTransactionAsync(_settings.Isolation, _settings.ReadOnly, _settings.Deferrable);
- internal Task RollbackAsync()
- => _client.RollbackAsync();
+ internal Task CommitAsync()
+ => _client.CommitAsync();
- internal async Task ExecuteInternalAsync(Func func)
+ internal Task RollbackAsync()
+ => _client.RollbackAsync();
+
+ internal async Task ExecuteInternalAsync(Func func)
+ {
+ lock (_lock)
{
- lock (_lock)
+ if (State != TransactionState.InTransaction)
{
- if (State != TransactionState.InTransaction)
- {
- throw new TransactionException($"Cannot preform query; this transaction {(State == TransactionState.InFailedTransaction ? "has failed" : "no longer exists")}.");
- }
+ throw new TransactionException(
+ $"Cannot preform query; this transaction {(State == TransactionState.InFailedTransaction ? "has failed" : "no longer exists")}.");
}
+ }
- EdgeDBException? innerException = null;
+ EdgeDBException? innerException = null;
- for (int i = 0; i != _settings.RetryAttempts; i++)
+ for (var i = 0; i != _settings.RetryAttempts; i++)
+ {
+ try
{
- try
- {
- await func().ConfigureAwait(false);
- return;
- }
- catch (EdgeDBException x) when (x.ShouldRetry)
- {
- innerException = x;
- }
+ await func().ConfigureAwait(false);
+ return;
+ }
+ catch (EdgeDBException x) when (x.ShouldRetry)
+ {
+ innerException = x;
}
-
- throw new TransactionException($"Transaction failed {_settings.RetryAttempts} time(s)", innerException);
}
- internal async Task ExecuteInternalAsync(Func> func)
+ throw new TransactionException($"Transaction failed {_settings.RetryAttempts} time(s)", innerException);
+ }
+
+ internal async Task ExecuteInternalAsync(Func> func)
+ {
+ lock (_lock)
{
- lock (_lock)
+ if (State != TransactionState.InTransaction)
{
- if (State != TransactionState.InTransaction)
- {
- throw new TransactionException($"Cannot preform query; this transaction {(State == TransactionState.InFailedTransaction ? "has failed" : "no longer exists")}.");
- }
+ throw new TransactionException(
+ $"Cannot preform query; this transaction {(State == TransactionState.InFailedTransaction ? "has failed" : "no longer exists")}.");
}
+ }
- EdgeDBException? innerException = null;
+ EdgeDBException? innerException = null;
- for (int i = 0; i != _settings.RetryAttempts; i++)
+ for (var i = 0; i != _settings.RetryAttempts; i++)
+ {
+ try
{
- try
- {
- return await func().ConfigureAwait(false);
- }
- catch (EdgeDBException x) when (x.ShouldRetry)
- {
- innerException = x;
- }
+ return await func().ConfigureAwait(false);
+ }
+ catch (EdgeDBException x) when (x.ShouldRetry)
+ {
+ innerException = x;
}
-
- throw new TransactionException($"Transaction failed {_settings.RetryAttempts} time(s)", innerException);
}
- ///
- public Task ExecuteAsync(string query, IDictionary? args = null,
- Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
- => ExecuteInternalAsync(() => _client.ExecuteAsync(query, args, capabilities, token));
-
- ///
- public Task> QueryAsync(string query, IDictionary? args = null,
- Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
- => ExecuteInternalAsync(() => _client.QueryAsync(query, args, capabilities, token));
-
- ///
- public Task QuerySingleAsync(string query, IDictionary? args = null,
- Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
- => ExecuteInternalAsync(() => _client.QuerySingleAsync(query, args, capabilities, token));
-
- ///
- public Task QueryRequiredSingleAsync(string query, IDictionary? args = null,
- Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
- => ExecuteInternalAsync(() => _client.QueryRequiredSingleAsync(query, args, capabilities, token));
-
- public Task QueryJsonAsync(string query, IDictionary? args = null,
- Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
- => ExecuteInternalAsync(() => _client.QueryJsonAsync(query, args, capabilities, token));
-
- public Task> QueryJsonElementsAsync(string query, IDictionary? args = null,
- Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default)
- => ExecuteInternalAsync(() => _client.QueryJsonElementsAsync(query, args, capabilities, token));
+ throw new TransactionException($"Transaction failed {_settings.RetryAttempts} time(s)", innerException);
}
+}
- public sealed class TransactionSettings
- {
- ///
- /// Gets the default transaction settings.
- ///
- public static TransactionSettings Default
- => new();
-
- ///
- /// Gets or sets the isolation within the transaction.
- ///
- public Isolation Isolation { get; set; } = Isolation.Serializable;
-
- ///
- /// Gets or sets whether or not the transaction is read-only.
- /// Any data modifications with insert, update, or delete are
- /// disallowed. Schema mutations via DDL are also disallowed.
- ///
- public bool ReadOnly { get; set; }
-
- ///
- /// Gets or sets whether or not the transaction is deferrable.
- /// The transaction can be set to deferrable mode only when
- /// is and
- /// is .
- ///
- ///
- /// When all three of
- /// these properties are selected for a transaction, the transaction
- /// may block when first acquiring its snapshot, after which it is able
- /// to run without the normal overhead of a
- /// transaction and without any risk of contributing to or being canceled
- /// by a serialization failure. This mode is well suited for long-running
- /// reports or backups.
- ///
- public bool Deferrable { get; set; }
-
- ///
- /// Gets or sets the number of attempts to retry the transaction before throwing.
- ///
- public uint RetryAttempts { get; set; } = 3;
- }
+public sealed class TransactionSettings
+{
+ ///
+ /// Gets the default transaction settings.
+ ///
+ public static TransactionSettings Default
+ => new();
+
+ ///
+ /// Gets or sets the isolation within the transaction.
+ ///
+ public Isolation Isolation { get; set; } = Isolation.Serializable;
+
+ ///
+ /// Gets or sets whether or not the transaction is read-only.
+ /// Any data modifications with insert, update, or delete are
+ /// disallowed. Schema mutations via DDL are also disallowed.
+ ///
+ public bool ReadOnly { get; set; }
+
+ ///
+ /// Gets or sets whether or not the transaction is deferrable.
+ /// The transaction can be set to deferrable mode only when
+ /// is and
+ /// is .
+ ///
+ ///
+ /// When all three of
+ /// these properties are selected for a transaction, the transaction
+ /// may block when first acquiring its snapshot, after which it is able
+ /// to run without the normal overhead of a
+ /// transaction and without any risk of contributing to or being canceled
+ /// by a serialization failure. This mode is well suited for long-running
+ /// reports or backups.
+ ///
+ public bool Deferrable { get; set; }
+
+ ///
+ /// Gets or sets the number of attempts to retry the transaction before throwing.
+ ///
+ public uint RetryAttempts { get; set; } = 3;
}
diff --git a/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs b/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs
index 4ac8c354..91566a6e 100644
--- a/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs
+++ b/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs
@@ -1,38 +1,30 @@
-using BenchmarkDotNet.Attributes;
-using EdgeDB.Binary;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+namespace EdgeDB.Tests.Benchmarks;
-namespace EdgeDB.Tests.Benchmarks
-{
- // commented out because of internalization of sendables.
- //[MemoryDiagnoser]
- //public class PacketWritingBenchmark
- //{
- // [Benchmark]
- // [ArgumentsSource(nameof(Packets))]
- // public Memory WritePacket(Sendable packet)
- // {
- // var p = new PacketWriter(packet.Size + 5);
- // packet!.Write(ref p, null!);
- // var data = p.GetBytes();
- // p.Dispose();
- // return data;
- // }
+// commented out because of internalization of sendables.
- // public IEnumerable Packets => new Sendable[]
- // {
- // new ClientHandshake()
- // {
- // MajorVersion = 1,
- // MinorVersion = 0,
- // Extensions = Array.Empty(),
- // ConnectionParameters = Array.Empty(),
- // }
- // };
- //}
-}
+//[MemoryDiagnoser]
+//public class PacketWritingBenchmark
+//{
+// [Benchmark]
+// [ArgumentsSource(nameof(Packets))]
+// public Memory WritePacket(Sendable packet)
+// {
+// var p = new PacketWriter(packet.Size + 5);
+// packet!.Write(ref p, null!);
+// var data = p.GetBytes();
+// p.Dispose();
+// return data;
+// }
+
+// public IEnumerable Packets => new Sendable[]
+// {
+// new ClientHandshake()
+// {
+// MajorVersion = 1,
+// MinorVersion = 0,
+// Extensions = Array.Empty(),
+// ConnectionParameters = Array.Empty(),
+// }
+// };
+//}
diff --git a/tests/EdgeDB.Tests.Integration/EdgeDB.Tests.Integration.csproj b/tests/EdgeDB.Tests.Integration/EdgeDB.Tests.Integration.csproj
index 50cb20d2..f5882179 100644
--- a/tests/EdgeDB.Tests.Integration/EdgeDB.Tests.Integration.csproj
+++ b/tests/EdgeDB.Tests.Integration/EdgeDB.Tests.Integration.csproj
@@ -8,14 +8,14 @@
-
-
-
-
+
+
+
+
-
+
diff --git a/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs b/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs
index 2736bec5..932ec519 100644
--- a/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs
+++ b/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs
@@ -1,194 +1,181 @@
using EdgeDB.Binary;
using EdgeDB.Utils;
using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
-using System.Runtime.CompilerServices;
+using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
-using System.Threading.Tasks;
-namespace EdgeDB.BinaryDebugger
+namespace EdgeDB.BinaryDebugger;
+
+internal class DebuggerClient : EdgeDBBinaryClient
{
+ private readonly StreamDuplexer _duplexer;
+
+ private Stream? _proxy;
+ private SslStream? _secureStream;
+ private NetworkStream? _stream;
- internal class DebuggerClient : EdgeDBBinaryClient
+ private TcpClient _tcpClient;
+
+ public DebuggerClient(EdgeDBConnection connection, EdgeDBConfig config, ulong? clientId = null)
+ : base(connection, config, null!, clientId)
{
- public StreamWriter Writer { get; }
- public FileStream FileStream { get; }
- internal override IBinaryDuplexer Duplexer => _duplexer;
+ if (File.Exists("./debug.log"))
+ File.Delete("./debug.log");
- public override bool IsConnected => _tcpClient.Connected;
+ _tcpClient = new TcpClient();
+ _duplexer = new StreamDuplexer(this);
- private Stream? _proxy;
- private StreamDuplexer _duplexer;
+ FileStream = File.OpenWrite("./debug.log");
+ Writer = new StreamWriter(FileStream, Encoding.UTF8);
+ }
- private TcpClient _tcpClient;
- private NetworkStream? _stream;
- private SslStream? _secureStream;
+ public StreamWriter Writer { get; }
+ public FileStream FileStream { get; }
+ internal override IBinaryDuplexer Duplexer => _duplexer;
- public DebuggerClient(EdgeDBConnection connection, EdgeDBConfig config, ulong? clientId = null)
- : base(connection, config, null!, clientId)
- {
- if (File.Exists("./debug.log"))
- File.Delete("./debug.log");
-
- _tcpClient = new();
- _duplexer = new(this);
-
- FileStream = File.OpenWrite("./debug.log");
- Writer = new StreamWriter(FileStream, Encoding.UTF8);
- }
+ public override bool IsConnected => _tcpClient.Connected;
- protected override async ValueTask GetStreamAsync(CancellationToken token = default)
- {
+ private PacketHeader? Header { get; set; }
- _tcpClient = new TcpClient();
+ protected override async ValueTask GetStreamAsync(CancellationToken token = default)
+ {
+ _tcpClient = new TcpClient();
- using var timeoutToken = CancellationTokenSource.CreateLinkedTokenSource(DisconnectCancelToken, token);
+ using var timeoutToken = CancellationTokenSource.CreateLinkedTokenSource(DisconnectCancelToken, token);
- timeoutToken.CancelAfter(ConnectionTimeout);
+ timeoutToken.CancelAfter(ConnectionTimeout);
- try
- {
- await _tcpClient.ConnectAsync(Connection.Hostname!, Connection.Port, timeoutToken.Token).ConfigureAwait(false);
- }
- catch (OperationCanceledException x) when (timeoutToken.IsCancellationRequested)
- {
- throw new TimeoutException("The connection timed out", x);
- }
- catch (SocketException x)
+ try
+ {
+ await _tcpClient.ConnectAsync(Connection.Hostname!, Connection.Port, timeoutToken.Token)
+ .ConfigureAwait(false);
+ }
+ catch (OperationCanceledException x) when (timeoutToken.IsCancellationRequested)
+ {
+ throw new TimeoutException("The connection timed out", x);
+ }
+ catch (SocketException x)
+ {
+ switch (x.SocketErrorCode)
{
- switch (x.SocketErrorCode)
- {
- case SocketError.ConnectionRefused
- or SocketError.ConnectionAborted
- or SocketError.ConnectionReset
- or SocketError.HostNotFound
- or SocketError.NotInitialized:
- throw new ConnectionFailedTemporarilyException(x.SocketErrorCode);
-
- default:
- throw;
- }
+ case SocketError.ConnectionRefused
+ or SocketError.ConnectionAborted
+ or SocketError.ConnectionReset
+ or SocketError.HostNotFound
+ or SocketError.NotInitialized:
+ throw new ConnectionFailedTemporarilyException(x.SocketErrorCode);
+
+ default:
+ throw;
}
+ }
- _stream = _tcpClient.GetStream();
+ _stream = _tcpClient.GetStream();
- _secureStream = new SslStream(_stream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
+ _secureStream = new SslStream(_stream, false, ValidateServerCertificate, null);
- var options = new SslClientAuthenticationOptions()
- {
- AllowRenegotiation = true,
- ApplicationProtocols = new List
- {
- new SslApplicationProtocol("edgedb-binary")
- },
- TargetHost = Connection.Hostname,
- EnabledSslProtocols = System.Security.Authentication.SslProtocols.None,
- CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
- };
+ var options = new SslClientAuthenticationOptions
+ {
+ AllowRenegotiation = true,
+ ApplicationProtocols = new List {new("edgedb-binary")},
+ TargetHost = Connection.Hostname,
+ EnabledSslProtocols = SslProtocols.None,
+ CertificateRevocationCheckMode = X509RevocationMode.NoCheck
+ };
- await _secureStream.AuthenticateAsClientAsync(options).ConfigureAwait(false);
+ await _secureStream.AuthenticateAsClientAsync(options).ConfigureAwait(false);
- _proxy = new StreamProxy(_secureStream, OnRead, OnWrite);
- return _proxy;
- }
+ _proxy = new StreamProxy(_secureStream, OnRead, OnWrite);
+ return _proxy;
+ }
- private bool ValidateServerCertificate(object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors)
- {
- if (Connection.TLSSecurity is TLSSecurityMode.Insecure)
- return true;
+ private bool ValidateServerCertificate(object sender, X509Certificate? certificate, X509Chain? chain,
+ SslPolicyErrors sslPolicyErrors)
+ {
+ if (Connection.TLSSecurity is TLSSecurityMode.Insecure)
+ return true;
- if (Connection.TLSCertificateAuthority is not null)
- {
- var cert = Connection.GetCertificate()!;
+ if (Connection.TLSCertificateAuthority is not null)
+ {
+ var cert = Connection.GetCertificate()!;
- X509Chain chain2 = new();
- chain2.ChainPolicy.ExtraStore.Add(cert);
- chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
- chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
+ X509Chain chain2 = new();
+ chain2.ChainPolicy.ExtraStore.Add(cert);
+ chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
+ chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
- bool isValid = chain2.Build(new X509Certificate2(certificate!));
- var chainRoot = chain2.ChainElements[^1].Certificate;
- isValid = isValid && chainRoot.RawData.SequenceEqual(cert.RawData);
+ var isValid = chain2.Build(new X509Certificate2(certificate!));
+ var chainRoot = chain2.ChainElements[^1].Certificate;
+ isValid = isValid && chainRoot.RawData.SequenceEqual(cert.RawData);
- return isValid;
- }
- else
- {
- return sslPolicyErrors is SslPolicyErrors.None;
- }
+ return isValid;
}
- private readonly struct PacketHeader
- {
- public readonly ServerMessageType Type { get; init; }
- public readonly int Length { get; init; }
- public readonly byte[] Raw { get; init; }
- }
+ return sslPolicyErrors is SslPolicyErrors.None;
+ }
- private PacketHeader? Header { get; set; }
-
- private void OnRead(int read, byte[] buffer, int offset, int count)
- {
- var copyBuffer = new byte[buffer.Length];
+ private void OnRead(int read, byte[] buffer, int offset, int count)
+ {
+ var copyBuffer = new byte[buffer.Length];
- buffer.CopyTo(copyBuffer, 0);
- var reader = new PacketReader(copyBuffer);
-
- if(read == 5)
- {
- var raw = copyBuffer.ToArray();
- // packet header
- Header = new PacketHeader
- {
- Type = (ServerMessageType)reader.ReadByte(),
- Length = reader.ReadInt32() - 4,
- Raw = raw[..5]
- };
- return;
- }
+ buffer.CopyTo(copyBuffer, 0);
+ var reader = new PacketReader(copyBuffer);
- if (Header.HasValue)
+ if (read == 5)
+ {
+ var raw = copyBuffer.ToArray();
+ // packet header
+ Header = new PacketHeader
{
- var memory = copyBuffer.AsMemory()[..read];
- var raw = HexConverter.ToHex(memory.ToArray());
-
- var factory = ProtocolProvider.GetPacketFactory(Header.Value.Type)!;
+ Type = (ServerMessageType)reader.ReadByte(), Length = reader.ReadInt32() - 4, Raw = raw[..5]
+ };
+ return;
+ }
- var packet = PacketSerializer.DeserializePacket(in factory, in memory);
+ if (Header.HasValue)
+ {
+ var memory = copyBuffer.AsMemory()[..read];
+ var raw = HexConverter.ToHex(memory.ToArray());
- Writer.WriteLine($"READING\n" +
- $"=======\n" +
- $"Packet Type: {Header.Value.Type}\n" +
- $"Raw: {HexConverter.ToHex(Header.Value.Raw)}{raw}\n" +
- $"{JsonConvert.SerializeObject(packet, Formatting.Indented, new JsonSerializerSettings { MaxDepth = 5 })}\n");
+ var factory = ProtocolProvider.GetPacketFactory(Header.Value.Type)!;
- Header = null;
- }
- }
+ var packet = PacketSerializer.DeserializePacket(in factory, in memory);
- private void OnWrite(byte[] buffer, int offset, int count)
- {
- Writer.WriteLine($"WRITING\n" +
+ Writer.WriteLine($"READING\n" +
$"=======\n" +
- $"Buffer: {EdgeDB.Utils.HexConverter.ToHex(buffer)}\n" +
- $"Type: {(ClientMessageTypes)buffer[0]}\n" +
- $"Length: {count}\n" +
- $"Offset: {offset}\n");
+ $"Packet Type: {Header.Value.Type}\n" +
+ $"Raw: {HexConverter.ToHex(Header.Value.Raw)}{raw}\n" +
+ $"{JsonConvert.SerializeObject(packet, Formatting.Indented, new JsonSerializerSettings {MaxDepth = 5})}\n");
+
+ Header = null;
}
+ }
- protected override ValueTask CloseStreamAsync(CancellationToken token = default)
- {
- _proxy?.Close();
- Writer.Flush();
- FileStream.Flush();
- FileStream.Close();
+ private void OnWrite(byte[] buffer, int offset, int count) =>
+ Writer.WriteLine($"WRITING\n" +
+ $"=======\n" +
+ $"Buffer: {HexConverter.ToHex(buffer)}\n" +
+ $"Type: {(ClientMessageTypes)buffer[0]}\n" +
+ $"Length: {count}\n" +
+ $"Offset: {offset}\n");
- return ValueTask.CompletedTask;
- }
+ protected override ValueTask CloseStreamAsync(CancellationToken token = default)
+ {
+ _proxy?.Close();
+ Writer.Flush();
+ FileStream.Flush();
+ FileStream.Close();
+
+ return ValueTask.CompletedTask;
+ }
+
+ private readonly struct PacketHeader
+ {
+ public readonly ServerMessageType Type { get; init; }
+ public readonly int Length { get; init; }
+ public readonly byte[] Raw { get; init; }
}
}
diff --git a/tools/EdgeDB.DocGenerator/EdgeDB.DocGenerator.csproj b/tools/EdgeDB.DocGenerator/EdgeDB.DocGenerator.csproj
index 1b34581d..68859c0f 100644
--- a/tools/EdgeDB.DocGenerator/EdgeDB.DocGenerator.csproj
+++ b/tools/EdgeDB.DocGenerator/EdgeDB.DocGenerator.csproj
@@ -8,11 +8,11 @@
-
+
-
+
diff --git a/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj b/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj
index 7935bd1d..117595a1 100644
--- a/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj
+++ b/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj
@@ -2,28 +2,28 @@
Exe
- net6.0
- enable
+ net6.0
+ enable
enable
- True
- 5
+ True
+ 5
- True
- 5
+ True
+ 5
-
-
+
+
-
+