Skip to content

Commit 5673cfa

Browse files
committed
Lazy loading navigation properties in EF storage
1 parent 05b2803 commit 5673cfa

File tree

15 files changed

+120
-37
lines changed

15 files changed

+120
-37
lines changed

src/Deveel.Webhooks.Service.EntityFramework/Webhooks/DbWebhookDeliveryResult.cs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,29 @@
1515
// Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
1616
#pragma warning disable CS8618
1717

18+
using Microsoft.EntityFrameworkCore.Infrastructure;
19+
20+
using System.Collections.ObjectModel;
21+
1822
namespace Deveel.Webhooks {
1923
/// <summary>
2024
/// Implements the <see cref="IWebhookDeliveryResult"/> interface to
2125
/// allow the storage of the result of a delivery attempt in a database
2226
/// </summary>
2327
public class DbWebhookDeliveryResult : IWebhookDeliveryResult {
28+
private readonly ILazyLoader lazyLoader;
29+
private DbEventInfo eventInfo;
30+
private DbWebhook webhook;
31+
private DbWebhookReceiver receiver;
32+
private List<DbWebhookDeliveryAttempt>? deliveryAttempts;
33+
34+
private DbWebhookDeliveryResult(ILazyLoader lazyLoader) {
35+
this.lazyLoader = lazyLoader;
36+
}
37+
38+
public DbWebhookDeliveryResult() {
39+
}
40+
2441
/// <summary>
2542
/// Gets or sets the database identifier of the delivery result.
2643
/// </summary>
@@ -40,7 +57,10 @@ public class DbWebhookDeliveryResult : IWebhookDeliveryResult {
4057
/// Gets or sets the database entity that describes the event
4158
/// that triggered the delivery of the webhook.
4259
/// </summary>
43-
public virtual DbEventInfo EventInfo { get; set; }
60+
public virtual DbEventInfo EventInfo {
61+
get => lazyLoader.Load(this, ref eventInfo);
62+
set => eventInfo = value;
63+
}
4464

4565
/// <summary>
4666
/// Gets or sets the database identifier of the event that triggered
@@ -52,7 +72,10 @@ public class DbWebhookDeliveryResult : IWebhookDeliveryResult {
5272
/// Gets or sets the database entity that describes the webhook
5373
/// that was delivered.
5474
/// </summary>
55-
public virtual DbWebhook Webhook { get; set; }
75+
public virtual DbWebhook Webhook {
76+
get => lazyLoader.Load(this, ref webhook);
77+
set => webhook = value;
78+
}
5679

5780
/// <summary>
5881
/// Gets or sets the database identifier of the webhook that was delivered
@@ -67,19 +90,26 @@ public class DbWebhookDeliveryResult : IWebhookDeliveryResult {
6790
/// Gets or sets the database entity that describes the receiver
6891
/// of the webhook.
6992
/// </summary>
70-
public virtual DbWebhookReceiver Receiver { get; set; }
93+
public virtual DbWebhookReceiver Receiver {
94+
get => lazyLoader.Load(this, ref receiver);
95+
set => receiver = value;
96+
}
7197

7298
/// <summary>
7399
/// Gets or sets the database identifier of the receiver of the webhook.
74100
/// </summary>
75101
public int? ReceiverId { get; set; }
76102

77-
IEnumerable<IWebhookDeliveryAttempt> IWebhookDeliveryResult.DeliveryAttempts => DeliveryAttempts.AsReadOnly();
103+
IEnumerable<IWebhookDeliveryAttempt> IWebhookDeliveryResult.DeliveryAttempts
104+
=> DeliveryAttempts?.AsReadOnly() ?? new ReadOnlyCollection<DbWebhookDeliveryAttempt>(new List<DbWebhookDeliveryAttempt>());
78105

79106
/// <summary>
80107
/// Gets or sets the list of delivery attempts that were made to deliver
81108
/// the webhook.
82109
/// </summary>
83-
public virtual List<DbWebhookDeliveryAttempt> DeliveryAttempts { get; set; }
110+
public virtual List<DbWebhookDeliveryAttempt>? DeliveryAttempts {
111+
get => lazyLoader.Load(this, ref deliveryAttempts);
112+
set => deliveryAttempts = value;
113+
}
84114
}
85115
}

src/Deveel.Webhooks.Service.EntityFramework/Webhooks/DbWebhookReceiver.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using Microsoft.EntityFrameworkCore.Infrastructure;
16+
1517
using System.Diagnostics.CodeAnalysis;
1618

1719
// Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
@@ -22,6 +24,16 @@ namespace Deveel.Webhooks {
2224
/// Represents a webhook receiver that is stored in a database
2325
/// </summary>
2426
public class DbWebhookReceiver : IWebhookReceiver {
27+
private readonly ILazyLoader lazyLoader;
28+
private List<DbWebhookReceiverHeader> headers;
29+
30+
private DbWebhookReceiver(ILazyLoader lazyLoader) {
31+
this.lazyLoader = lazyLoader;
32+
}
33+
34+
public DbWebhookReceiver() {
35+
}
36+
2537
/// <summary>
2638
/// Gets or sets the database identifier of the
2739
/// receiver entity
@@ -41,7 +53,7 @@ public class DbWebhookReceiver : IWebhookReceiver {
4153
public virtual DbWebhookSubscription? Subscription { get; set; }
4254

4355
/// <inheritdoc/>
44-
public string? SubscriptionName { get; set; }
56+
public string? SubscriptionName { get; set; }
4557

4658
/// <inheritdoc/>
4759
public string DestinationUrl { get; set; }
@@ -55,7 +67,10 @@ IEnumerable<KeyValuePair<string, string>> IWebhookReceiver.Headers
5567
/// to the receiver.
5668
/// </summary>
5769
/// <seealso cref="IWebhookReceiver.Headers"/>
58-
public virtual List<DbWebhookReceiverHeader> Headers { get; set; }
70+
public virtual List<DbWebhookReceiverHeader> Headers {
71+
get => lazyLoader.Load(this, ref headers);
72+
set => headers = value;
73+
}
5974

6075
/// <inheritdoc/>
6176
public string BodyFormat { get; set; }

src/Deveel.Webhooks.Service.EntityFramework/Webhooks/DbWebhookReceiverHeader.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using Microsoft.EntityFrameworkCore.Infrastructure;
16+
1517
// Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
1618
#pragma warning disable CS8618
1719

src/Deveel.Webhooks.Service.EntityFramework/Webhooks/DbWebhookSubscription.cs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,27 @@
1616
#pragma warning disable CS8618
1717

1818
using System.Diagnostics.CodeAnalysis;
19+
using Microsoft.EntityFrameworkCore.Infrastructure;
1920

2021
namespace Deveel.Webhooks {
2122
/// <summary>
2223
/// Represents the entity that describes a webhook subscription
2324
/// that is stored in a database.
2425
/// </summary>
2526
public class DbWebhookSubscription : IWebhookSubscription {
27+
private readonly ILazyLoader lazyLoader;
28+
private List<DbWebhookSubscriptionEvent>? events;
29+
private List<DbWebhookFilter>? filters;
30+
private List<DbWebhookSubscriptionHeader>? headers;
31+
private List<DbWebhookSubscriptionProperty>? properties;
32+
33+
private DbWebhookSubscription(ILazyLoader lazyLoader) {
34+
this.lazyLoader = lazyLoader;
35+
}
36+
37+
public DbWebhookSubscription() {
38+
}
39+
2640
/// <summary>
2741
/// Gets or sets the database identifier of the subscription entity.
2842
/// </summary>
@@ -67,14 +81,20 @@ public class DbWebhookSubscription : IWebhookSubscription {
6781
/// <summary>
6882
/// Gets or sets the list of events that are subscribed.
6983
/// </summary>
70-
public virtual List<DbWebhookSubscriptionEvent> Events { get; set; }
84+
public virtual List<DbWebhookSubscriptionEvent>? Events {
85+
get => lazyLoader.Load(this, ref events);
86+
set => events = value;
87+
}
7188

72-
IEnumerable<IWebhookFilter>? IWebhookSubscription.Filters => Filters.AsReadOnly();
89+
IEnumerable<IWebhookFilter>? IWebhookSubscription.Filters => Filters?.AsReadOnly();
7390

7491
/// <summary>
7592
/// Gets or sets the list of filters that are applied to the subscription.
7693
/// </summary>
77-
public List<DbWebhookFilter> Filters { get; set; }
94+
public List<DbWebhookFilter>? Filters {
95+
get => lazyLoader.Load(this, ref filters);
96+
set => filters = value;
97+
}
7898

7999
IDictionary<string, string>? IWebhookSubscription.Headers =>
80100
Headers?.ToDictionary(x => x.Key, x => x.Value);
@@ -86,11 +106,17 @@ public class DbWebhookSubscription : IWebhookSubscription {
86106
/// <summary>
87107
/// Gets or sets the list of headers that are applied to the subscription.
88108
/// </summary>
89-
public virtual List<DbWebhookSubscriptionHeader> Headers { get; set; }
109+
public virtual List<DbWebhookSubscriptionHeader>? Headers {
110+
get => lazyLoader.Load(this, ref headers);
111+
set => headers = value;
112+
}
90113

91114
/// <summary>
92115
/// Gets or sets the list of properties of the subscription.
93116
/// </summary>
94-
public virtual List<DbWebhookSubscriptionProperty> Properties { get; set; }
117+
public virtual List<DbWebhookSubscriptionProperty>? Properties {
118+
get => lazyLoader.Load(this, ref properties);
119+
set => properties = value;
120+
}
95121
}
96122
}

src/Deveel.Webhooks.Service.EntityFramework/Webhooks/EntityWebhookDeliveryResultRepository_T.cs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,32 @@ public EntityWebhookDeliveryResultRepository(WebhookDbContext context, ILogger<E
4343
: base(context, logger) {
4444
}
4545

46-
/// <summary>
47-
/// Gets a queryable object to query the delivery results,
48-
/// including the related entities (webhook, event, delivery
49-
/// attempts, receiver).
50-
/// </summary>
51-
/// <returns>
52-
/// Returns an <see cref="IQueryable{TResult}"/> object that can be used
53-
/// to query the delivery results.
54-
/// </returns>
55-
public override IQueryable<TResult> AsQueryable()
56-
{
57-
return Entities
58-
.Include(x => x.Webhook)
59-
.Include(x => x.EventInfo)
60-
.Include(x => x.DeliveryAttempts)
61-
.Include(x => x.Receiver);
62-
}
46+
///// <summary>
47+
///// Gets a queryable object to query the delivery results,
48+
///// including the related entities (webhook, event, delivery
49+
///// attempts, receiver).
50+
///// </summary>
51+
///// <returns>
52+
///// Returns an <see cref="IQueryable{TResult}"/> object that can be used
53+
///// to query the delivery results.
54+
///// </returns>
55+
//public override IQueryable<TResult> AsQueryable()
56+
//{
57+
// return Entities
58+
// .Include(x => x.Webhook)
59+
// .Include(x => x.EventInfo)
60+
// .Include(x => x.DeliveryAttempts)
61+
// .Include(x => x.Receiver);
62+
//}
6363

64-
/// <inheritdoc/>
65-
public override async Task<TResult?> FindAsync(int key, CancellationToken cancellationToken = default)
66-
{
67-
// This overload to the identity key uses the 'FindAsync' method
68-
// to include all the related entities
69-
// TODO: find a better way to include the related entities through lazy loading
70-
return await FindFirstAsync(Query.Where<TResult>(x => x.Id == key), cancellationToken);
71-
}
64+
///// <inheritdoc/>
65+
//public override async Task<TResult?> FindAsync(int key, CancellationToken cancellationToken = default)
66+
//{
67+
// // This overload to the identity key uses the 'FindAsync' method
68+
// // to include all the related entities
69+
// // TODO: find a better way to include the related entities through lazy loading
70+
// return await FindFirstAsync(Query.Where<TResult>(x => x.Id == key), cancellationToken);
71+
//}
7272

7373
/// <inheritdoc/>
7474
public async Task<TResult?> FindByWebhookIdAsync(string webhookId, CancellationToken cancellationToken) {

test/Deveel.Webhooks.DynamicLinq.XUnit/Deveel.Webhooks.DynamicLinq.XUnit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<IsTestProject>true</IsTestProject>
55
<NoWarn>CS8618</NoWarn>
6+
<RunSettingsFilePath>D:\deveel\deveel.webhooks\test\Deveel.Webhooks.DynamicLinq.XUnit\bin\Debug\net7.0\fine-code-coverage\coverage-tool-output\Deveel.Webhooks.DynamicLinq.XUnit %28net7.0%29-fcc-mscodecoverage-generated.runsettings</RunSettingsFilePath>
67
</PropertyGroup>
78

89
<ItemGroup>

test/Deveel.Webhooks.EntityFramework.XUnit/Deveel.Webhooks.EntityFramework.XUnit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<IsTestProject>true</IsTestProject>
5+
<RunSettingsFilePath>D:\deveel\deveel.webhooks\test\Deveel.Webhooks.EntityFramework.XUnit\bin\Debug\net6.0\fine-code-coverage\coverage-tool-output\Deveel.Webhooks.EntityFramework.XUnit %28net6.0%29-fcc-mscodecoverage-generated.runsettings</RunSettingsFilePath>
56
</PropertyGroup>
67

78
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">

test/Deveel.Webhooks.MongoDb.XUnit/Deveel.Webhooks.MongoDb.XUnit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<IsTestProject>true</IsTestProject>
55
<NoWarn>1701;1702;CS8618</NoWarn>
6+
<RunSettingsFilePath>D:\deveel\deveel.webhooks\test\Deveel.Webhooks.MongoDb.XUnit\bin\Debug\net6.0\fine-code-coverage\coverage-tool-output\Deveel.Webhooks.MongoDb.XUnit %28net6.0%29-fcc-mscodecoverage-generated.runsettings</RunSettingsFilePath>
67
</PropertyGroup>
78

89
<ItemGroup>

test/Deveel.Webhooks.Receiver.Facebook.XUnit/Deveel.Webhooks.Receiver.Facebook.XUnit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<IsTestProject>true</IsTestProject>
5+
<RunSettingsFilePath>D:\deveel\deveel.webhooks\test\Deveel.Webhooks.Receiver.Facebook.XUnit\bin\Debug\net7.0\fine-code-coverage\coverage-tool-output\Deveel.Webhooks.Receiver.Facebook.XUnit %28net7.0%29-fcc-mscodecoverage-generated.runsettings</RunSettingsFilePath>
56
</PropertyGroup>
67

78
<ItemGroup>

test/Deveel.Webhooks.Receiver.NewtonsoftJson.XUnit/Deveel.Webhooks.Receiver.NewtonsoftJson.XUnit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<IsTestProject>true</IsTestProject>
5+
<RunSettingsFilePath>D:\deveel\deveel.webhooks\test\Deveel.Webhooks.Receiver.NewtonsoftJson.XUnit\bin\Debug\net6.0\fine-code-coverage\coverage-tool-output\Deveel.Webhooks.Receiver.NewtonsoftJson.XUnit %28net6.0%29-fcc-mscodecoverage-generated.runsettings</RunSettingsFilePath>
56
</PropertyGroup>
67

78
<ItemGroup>

0 commit comments

Comments
 (0)