diff --git a/JSONAPI.EntityFramework.Tests/EntityConverterTests.cs b/JSONAPI.EntityFramework.Tests/EntityConverterTests.cs index 33f2412b..20be241a 100644 --- a/JSONAPI.EntityFramework.Tests/EntityConverterTests.cs +++ b/JSONAPI.EntityFramework.Tests/EntityConverterTests.cs @@ -2,6 +2,7 @@ using System.Text; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using JSONAPI.Core; @@ -121,7 +122,7 @@ public void SerializeTest() [TestMethod] [DeploymentItem(@"Data\Post.json")] - public void DeserializePostIntegrationTest() + public async Task DeserializePostIntegrationTest() { // Arrange JsonApiFormatter formatter = new JSONAPI.Json.JsonApiFormatter(); @@ -144,8 +145,8 @@ public void DeserializePostIntegrationTest() // Act Post pUpdated; - pUpdated = (Post)formatter.ReadFromStreamAsync(typeof(Post), stream, (System.Net.Http.HttpContent)null, (System.Net.Http.Formatting.IFormatterLogger)null).Result; - pUpdated = materializer.MaterializeUpdate(pUpdated); + pUpdated = (Post)await formatter.ReadFromStreamAsync(typeof(Post), stream, (System.Net.Http.HttpContent)null, (System.Net.Http.Formatting.IFormatterLogger)null); + pUpdated = await materializer.MaterializeUpdateAsync(pUpdated); // Assert Assert.AreEqual(a, pUpdated.Author); @@ -156,7 +157,7 @@ public void DeserializePostIntegrationTest() } [TestMethod] - public void UnderpostingTest() + public async Task UnderpostingTest() { // Arrange JsonApiFormatter formatter = new JSONAPI.Json.JsonApiFormatter(); @@ -172,8 +173,8 @@ public void UnderpostingTest() // Act Post pUpdated; - pUpdated = (Post)formatter.ReadFromStreamAsync(typeof(Post), stream, (System.Net.Http.HttpContent)null, (System.Net.Http.Formatting.IFormatterLogger)null).Result; - pUpdated = materializer.MaterializeUpdate(pUpdated); + pUpdated = (Post)await formatter.ReadFromStreamAsync(typeof(Post), stream, (System.Net.Http.HttpContent)null, (System.Net.Http.Formatting.IFormatterLogger)null); + pUpdated = await materializer.MaterializeUpdateAsync(pUpdated); // Assert Assert.AreEqual(previousCommentsCount, pUpdated.Comments.Count, "Comments were wiped out!"); diff --git a/JSONAPI.EntityFramework/EntityFrameworkMaterializer.cs b/JSONAPI.EntityFramework/EntityFrameworkMaterializer.cs index 751f2c9f..635128d2 100644 --- a/JSONAPI.EntityFramework/EntityFrameworkMaterializer.cs +++ b/JSONAPI.EntityFramework/EntityFrameworkMaterializer.cs @@ -35,7 +35,7 @@ public EntityFrameworkMaterializer(DbContext context) : base() /// /// /// - public virtual object GetById(Type type, params Object[] idValues) + public virtual Task GetByIdAsync(Type type, params Object[] idValues) { //TODO: How to react if the type isn't in the context? @@ -58,20 +58,20 @@ public virtual object GetById(Type type, params Object[] idValues) i++; } } - return this.context.Set(type).Find(idv2); + return this.context.Set(type).FindAsync(idv2); } - public T GetById(params Object[] idValues) + public async Task GetByIdAsync(params Object[] idValues) { - return (T)GetById(typeof(T), idValues); + return (T) await GetByIdAsync(typeof(T), idValues); } - public T Materialize(T ephemeral) + public async Task MaterializeAsync(T ephemeral) { - return (T)Materialize(typeof(T), ephemeral); + return (T) await MaterializeAsync(typeof(T), ephemeral); } - public virtual object Materialize(Type type, object ephemeral) + public virtual async Task MaterializeAsync(Type type, object ephemeral) { IEnumerable keyNames = GetKeyNames(type); List idValues = new List(); @@ -90,7 +90,7 @@ public virtual object Materialize(Type type, object ephemeral) object retval = null; if (!anyNull) { - retval = context.Set(type).Find(idValues.ToArray()); + retval = await context.Set(type).FindAsync(idValues.ToArray()); } if (retval == null) { @@ -101,22 +101,56 @@ public virtual object Materialize(Type type, object ephemeral) { // For a new object, if a key is specified, we want to merge the key, at least. // For simplicity then, make the behavior equivalent to MergeMaterialize in this case. - this.Merge(type, ephemeral, retval); + await this.Merge(type, ephemeral, retval); } } return retval; } + public async Task MaterializeUpdateAsync(T ephemeral) + { + return (T) await MaterializeUpdateAsync(typeof(T), ephemeral); + } + + public async Task MaterializeUpdateAsync(Type type, object ephemeral) + { + object material = await MaterializeAsync(type, ephemeral); + await this.Merge(type, ephemeral, material); + return material; + } + + #endregion + + #region Obsolete IMaterializer contract methods + + public T GetById(params object[] keyValues) + { + return GetByIdAsync(keyValues).Result; + } + + public object GetById(Type type, params object[] keyValues) + { + return GetByIdAsync(type, keyValues).Result; + } + + public T Materialize(T ephemeral) + { + return MaterializeAsync(ephemeral).Result; + } + + public object Materialize(Type type, object ephemeral) + { + return MaterializeAsync(type, ephemeral).Result; + } + public T MaterializeUpdate(T ephemeral) { - return (T)MaterializeUpdate(typeof(T), ephemeral); + return MaterializeUpdateAsync(ephemeral).Result; } public object MaterializeUpdate(Type type, object ephemeral) { - object material = Materialize(type, ephemeral); - this.Merge(type, ephemeral, material); - return material; + return MaterializeUpdateAsync(type, ephemeral).Result; } #endregion @@ -246,7 +280,7 @@ protected EntityKey MaterializeEntityKey(Type type, object obj) return key; } - private void Merge (Type type, object ephemeral, object material) + private async Task Merge (Type type, object ephemeral, object material) { PropertyInfo[] props = type.GetProperties(); foreach (PropertyInfo prop in props) @@ -286,7 +320,7 @@ private void Merge (Type type, object ephemeral, object material) foreach (EntityKey key in ephemeralKeys.Except(materialKeys)) { object[] idParams = key.EntityKeyValues.Select(ekv => ekv.Value).ToArray(); - object obj = GetById(elementType, idParams); + object obj = await GetByIdAsync(elementType, idParams); mmadd.Invoke(materialMany, new object[] { obj }); } // Remove from hasMany @@ -294,7 +328,7 @@ private void Merge (Type type, object ephemeral, object material) foreach (EntityKey key in materialKeys.Except(ephemeralKeys)) { object[] idParams = key.EntityKeyValues.Select(ekv => ekv.Value).ToArray(); - object obj = GetById(elementType, idParams); + object obj = await GetByIdAsync(elementType, idParams); mmremove.Invoke(materialMany, new object[] { obj }); } } @@ -312,7 +346,7 @@ private void Merge (Type type, object ephemeral, object material) if (materialKey != ephemeralKey) { object[] idParams = ephemeralKey.EntityKeyValues.Select(ekv => ekv.Value).ToArray(); - prop.SetValue(material, GetById(prop.PropertyType, idParams), null); + prop.SetValue(material, await GetByIdAsync(prop.PropertyType, idParams), null); } // else, } @@ -328,6 +362,5 @@ private void Merge (Type type, object ephemeral, object material) } } - } } diff --git a/JSONAPI.EntityFramework/Http/ApiController.cs b/JSONAPI.EntityFramework/Http/ApiController.cs index 6d175235..3300670b 100644 --- a/JSONAPI.EntityFramework/Http/ApiController.cs +++ b/JSONAPI.EntityFramework/Http/ApiController.cs @@ -37,14 +37,14 @@ protected override IQueryable QueryableFactory(Core.IMaterializer materialize return ((EntityFrameworkMaterializer)materializer).DbContext.Set(); } - public override IList Post(IList postedObjs) + public override async Task> Post(IList postedObjs) { var materializer = this.MaterializerFactory(); List materialList = new List(); foreach (T postedObj in postedObjs) { DbContext context = materializer.DbContext; - var material = materializer.MaterializeUpdate(postedObj); + var material = await materializer.MaterializeUpdateAsync(postedObj); if (context.Entry(material).State == EntityState.Added) { context.SaveChanges(); @@ -61,28 +61,28 @@ public override IList Post(IList postedObjs) return materialList; } - public override IList Put(string id, IList putObjs) + public override async Task> Put(string id, IList putObjs) { var materializer = this.MaterializerFactory(); DbContext context = materializer.DbContext; List materialList = new List(); foreach (T putObj in putObjs) { - var material = materializer.MaterializeUpdate(putObj); + var material = await materializer.MaterializeUpdateAsync(putObj); materialList.Add(material); } context.SaveChanges(); return materialList; } - public override void Delete(string id) + public override async Task Delete(string id) { var materializer = this.MaterializerFactory(); DbContext context = materializer.DbContext; - T target = materializer.GetById(id); + T target = await materializer.GetByIdAsync(id); context.Set().Remove(target); context.SaveChanges(); - base.Delete(id); + await base.Delete(id); } protected override void Dispose(bool disposing) diff --git a/JSONAPI/Core/IMaterializer.cs b/JSONAPI/Core/IMaterializer.cs index 37982a00..c669c406 100644 --- a/JSONAPI/Core/IMaterializer.cs +++ b/JSONAPI/Core/IMaterializer.cs @@ -8,12 +8,18 @@ namespace JSONAPI.Core { public interface IMaterializer { + Task GetByIdAsync(params Object[] keyValues); + Task GetByIdAsync(Type type, params Object[] keyValues); + Task MaterializeAsync(T ephemeral); + Task MaterializeAsync(Type type, object ephemeral); + Task MaterializeUpdateAsync(T ephemeral); + Task MaterializeUpdateAsync(Type type, object ephemeral); - T GetById(params Object[] keyValues); - object GetById(Type type, params Object[] keyValues); - T Materialize(T ephemeral); - object Materialize(Type type, object ephemeral); - T MaterializeUpdate(T ephemeral); - object MaterializeUpdate(Type type, object ephemeral); + [Obsolete]T GetById(params Object[] keyValues); + [Obsolete]object GetById(Type type, params Object[] keyValues); + [Obsolete]T Materialize(T ephemeral); + [Obsolete]object Materialize(Type type, object ephemeral); + [Obsolete]T MaterializeUpdate(T ephemeral); + [Obsolete]object MaterializeUpdate(Type type, object ephemeral); } } diff --git a/JSONAPI/Http/ApiController.cs b/JSONAPI/Http/ApiController.cs index f1f176d7..947fbcc0 100644 --- a/JSONAPI/Http/ApiController.cs +++ b/JSONAPI/Http/ApiController.cs @@ -4,6 +4,7 @@ using System.Text; using System.Net; using System.Net.Http; +using System.Threading.Tasks; using System.Web.Http; using System.Reflection; using JSONAPI.Core; @@ -51,7 +52,7 @@ public virtual IQueryable Get() return es; } - public virtual IEnumerable Get(string id) + public virtual async Task> Get(string id) { IMaterializer materializer = MaterializerFactory(); @@ -67,7 +68,7 @@ public virtual IEnumerable Get(string id) } foreach (string singleid in arrIds) { - T hit = materializer.GetById(singleid); + T hit = await materializer.GetByIdAsync(singleid); if (hit != null) { results.Add(hit); @@ -85,29 +86,29 @@ public virtual IEnumerable Get(string id) /// /// /// - public virtual IList Post([FromBody] IList postedObjs) + public virtual Task> Post([FromBody] IList postedObjs) { foreach(T postedObj in postedObjs) { IMaterializer materializer = this.MaterializerFactory(); } - return postedObjs; + return Task.FromResult(postedObjs); } /// - /// Similar to Post, this method doesn't do much. It calls MaterializeUpdate() on the + /// Similar to Post, this method doesn't do much. It calls MaterializeUpdateAsync() on the /// input and returns it. It should probably always be overridden. /// /// /// /// - public virtual IList Put(string id, IList putObjs) + public virtual async Task> Put(string id, IList putObjs) { IMaterializer materializer = this.MaterializerFactory(); IList materialList = new List(); foreach (T putObj in putObjs) { - materialList.Add(materializer.MaterializeUpdate(putObj)); + materialList.Add(await materializer.MaterializeUpdateAsync(putObj)); } return materialList; } @@ -116,9 +117,9 @@ public virtual IList Put(string id, IList putObjs) /// A no-op method. This should be overriden in subclasses if Delete is to be supported. /// /// - public virtual void Delete(string id) + public virtual Task Delete(string id) { - return; + return Task.FromResult(0); } } }