Fauna v10 .NET/C# Driver 0.2.0-beta
 
Loading...
Searching...
No Matches
DataContext.cs
Go to the documentation of this file.
1using System.Collections.Immutable;
2using System.Diagnostics.CodeAnalysis;
3using System.Reflection;
4using System.Runtime.CompilerServices;
5using Fauna.Mapping;
6
7namespace Fauna;
8
9public abstract class DataContext : BaseClient
10{
11 private bool _initialized = false;
12 [AllowNull]
13 private IReadOnlyDictionary<Type, ICollection> _collections = null!;
14 [AllowNull]
15 private Client _client = null!;
16 [AllowNull]
17 private MappingContext _ctx = null!;
18
19 internal override MappingContext MappingCtx { get => _ctx; }
20 internal Linq.LookupTable LookupTable { get => new Linq.LookupTable(_ctx); }
21
22 internal void Init(Client client, Dictionary<Type, ICollection> collections, MappingContext ctx)
23 {
24 _client = client;
25 _collections = collections.ToImmutableDictionary();
26 _ctx = ctx;
27
28 foreach (var col in collections.Values)
29 {
30 ((Linq.QuerySource)col).SetContext(this);
31 }
32
33 _initialized = true;
34 }
35
36 // IClient impl
37
38 internal override Task<QuerySuccess<T>> QueryAsyncInternal<T>(
39 Query query,
40 Serialization.ISerializer<T> serializer,
42 QueryOptions? queryOptions,
43 CancellationToken cancel)
44 {
45 CheckInitialization();
46 return _client.QueryAsyncInternal(query, serializer, ctx, queryOptions, cancel);
47 }
48
49 // Schema DSL
50
51 [AttributeUsage(AttributeTargets.Class)]
52 public class NameAttribute : Attribute
53 {
54 internal readonly string Name;
55
56 public NameAttribute(string name)
57 {
58 Name = name;
59 }
60 }
61
62 public interface ICollection : Linq.IQuerySource
63 {
64 public string Name { get; }
65 public Type DocType { get; }
66 }
67
68 public abstract class Collection<Doc> : Linq.QuerySource<Doc>, ICollection
69 {
70 public string Name { get; }
71 public Type DocType { get => typeof(Doc); }
72
73 public Collection()
74 {
75 var nameAttr = this.GetType().GetCustomAttribute<NameAttribute>();
76 Name = nameAttr?.Name ?? typeof(Doc).Name;
77 SetQuery<Doc>(Linq.IntermediateQueryHelpers.CollectionAll(this));
78 }
79
80 // index call DSL
81
82 protected IndexCall Index(string? name = null, [CallerMemberName] string? auto = null)
83 {
84 if (name is null && auto is not null)
85 {
86 name = FieldName.Canonical(auto);
87 }
88
89 if (string.IsNullOrEmpty(name))
90 throw new ArgumentException($"{nameof(name)} cannot be null or empty.");
91
92 return new IndexCall(this, name, Ctx);
93 }
94
95 protected class IndexCall
96 {
97 private readonly ICollection _coll;
98 private readonly string _name;
99 private readonly DataContext _ctx;
100
101 public IndexCall(ICollection coll, string name, DataContext ctx)
102 {
103 _coll = coll;
104 _name = name;
105 _ctx = ctx;
106 }
107
108 public Index<Doc> Call() => Call(new object[] { });
109
110 public Index<Doc> Call(object a1) => Call(new object[] { a1 });
111
112 public Index<Doc> Call(object a1, object a2) => Call(new object[] { a1, a2 });
113
114 public Index<Doc> Call(object a1, object a2, object a3) => Call(new object[] { a1, a2, a3 });
115
116 public Index<Doc> Call(object[] args) => new Index<Doc>(_coll, _name, args, _ctx);
117
118 }
119 }
120
121 public interface IIndex : Linq.IQuerySource
122 {
123 public ICollection Collection { get; }
124 public string Name { get; }
125 public Type DocType { get; }
126 public object[] Args { get; }
127 }
128
129 public class Index<Doc> : Linq.QuerySource<Doc>, IIndex
130 {
131 public ICollection Collection { get; }
132 public string Name { get; }
133 public Type DocType { get => typeof(Doc); }
134 public object[] Args { get; }
135
136 internal Index(ICollection coll, string name, object[] args, DataContext ctx)
137 {
138 Collection = coll;
139 Name = name;
140 Args = args;
141 Ctx = ctx;
142 SetQuery<Doc>(Linq.IntermediateQueryHelpers.CollectionIndex(this));
143 }
144 }
145
146 // UDF / Function DSL
147
148 public interface IFunction : Linq.IQuerySource
149 {
150 public string Name { get; }
151 public object[] Args { get; }
152 }
153
154 protected class FunctionCall<T> where T : notnull
155 {
156
157 public string Name { get; }
158 private readonly DataContext _ctx;
159
160 public FunctionCall(string name, DataContext ctx)
161 {
162 Name = name;
163 _ctx = ctx;
164 }
165
166 public T Call() => Call(Array.Empty<object>());
167
168 public T Call(object a1) => Call(new[] { a1 });
169
170 public T Call(object a1, object a2) => Call(new[] { a1, a2 });
171
172 public T Call(object a1, object a2, object a3) => Call(new[] { a1, a2, a3 });
173
174 public T Call(object[] args) => CallAsync(args).Result;
175
176 public async Task<T> CallAsync() => await CallAsync(Array.Empty<object>());
177
178 public async Task<T> CallAsync(object a1) => await CallAsync(new[] { a1 });
179
180 public async Task<T> CallAsync(object a1, object a2) => await CallAsync(new[] { a1, a2 });
181
182 public async Task<T> CallAsync(object a1, object a2, object a3) => await CallAsync(new[] { a1, a2, a3 });
183
184 public async Task<T> CallAsync(object[] args)
185 {
186 var q = Linq.IntermediateQueryHelpers.Function(Name, args);
187 return (await _ctx.QueryAsync<T>(q)).Data;
188 }
189
190 }
191
192 protected FunctionCall<T> Fn<T>(string name = "", [CallerMemberName] string callerName = "") where T : notnull
193 {
194 var fnName = name == "" ? callerName : name;
195 return new FunctionCall<T>(fnName, this);
196 }
197
198 protected Col GetCollection<Col>() where Col : ICollection
199 {
200 CheckInitialization();
201 return (Col)_collections[typeof(Col)];
202 }
203
204 private void CheckInitialization()
205 {
206 if (!_initialized)
207 {
208 throw new InvalidOperationException(
209 "Uninitialized context. DataContext sub-classes must be instantiated using a client's .DataContext() method.");
210 }
211
212 }
213}
The base class for Client and DataContext.
Definition IClient.cs:345
Represents a client for interacting with a Fauna.
Definition Client.cs:14
Index< Doc > Call(object a1, object a2, object a3)
IndexCall(ICollection coll, string name, DataContext ctx)
Index< Doc > Call(object a1, object a2)
Index< Doc > Call(object[] args)
IndexCall Index(string? name=null, [CallerMemberName] string? auto=null)
async Task< T > CallAsync()
T Call(object a1, object a2, object a3)
async Task< T > CallAsync(object a1, object a2)
T Call(object a1, object a2)
async Task< T > CallAsync(object a1)
FunctionCall(string name, DataContext ctx)
async Task< T > CallAsync(object a1, object a2, object a3)
async Task< T > CallAsync(object[] args)
FunctionCall< T > Fn< T >(string name="", [CallerMemberName] string callerName="")
A class representing the mapping context to be used during serialization and deserialization.
Represents the abstract base class for constructing FQL queries.
Definition Query.cs:11
Represents the options for customizing Fauna queries.
Definition Client.cs:8