Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions JSONAPI.EntityFramework.Tests/EntityConverterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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<Post>(pUpdated);
pUpdated = (Post)await formatter.ReadFromStreamAsync(typeof(Post), stream, (System.Net.Http.HttpContent)null, (System.Net.Http.Formatting.IFormatterLogger)null);
pUpdated = await materializer.MaterializeUpdateAsync<Post>(pUpdated);

// Assert
Assert.AreEqual(a, pUpdated.Author);
Expand All @@ -156,7 +157,7 @@ public void DeserializePostIntegrationTest()
}

[TestMethod]
public void UnderpostingTest()
public async Task UnderpostingTest()
{
// Arrange
JsonApiFormatter formatter = new JSONAPI.Json.JsonApiFormatter();
Expand All @@ -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<Post>(pUpdated);
pUpdated = (Post)await formatter.ReadFromStreamAsync(typeof(Post), stream, (System.Net.Http.HttpContent)null, (System.Net.Http.Formatting.IFormatterLogger)null);
pUpdated = await materializer.MaterializeUpdateAsync<Post>(pUpdated);

// Assert
Assert.AreEqual(previousCommentsCount, pUpdated.Comments.Count, "Comments were wiped out!");
Expand Down
69 changes: 51 additions & 18 deletions JSONAPI.EntityFramework/EntityFrameworkMaterializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public EntityFrameworkMaterializer(DbContext context) : base()
/// <param name="type"></param>
/// <param name="idValues"></param>
/// <returns></returns>
public virtual object GetById(Type type, params Object[] idValues)
public virtual Task<object> GetByIdAsync(Type type, params Object[] idValues)
{
//TODO: How to react if the type isn't in the context?

Expand All @@ -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<T>(params Object[] idValues)
public async Task<T> GetByIdAsync<T>(params Object[] idValues)
{
return (T)GetById(typeof(T), idValues);
return (T) await GetByIdAsync(typeof(T), idValues);
}

public T Materialize<T>(T ephemeral)
public async Task<T> MaterializeAsync<T>(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<object> MaterializeAsync(Type type, object ephemeral)
{
IEnumerable<string> keyNames = GetKeyNames(type);
List<Object> idValues = new List<Object>();
Expand All @@ -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)
{
Expand All @@ -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<T> MaterializeUpdateAsync<T>(T ephemeral)
{
return (T) await MaterializeUpdateAsync(typeof(T), ephemeral);
}

public async Task<object> 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<T>(params object[] keyValues)
{
return GetByIdAsync<T>(keyValues).Result;
}

public object GetById(Type type, params object[] keyValues)
{
return GetByIdAsync(type, keyValues).Result;
}

public T Materialize<T>(T ephemeral)
{
return MaterializeAsync<T>(ephemeral).Result;
}

public object Materialize(Type type, object ephemeral)
{
return MaterializeAsync(type, ephemeral).Result;
}

public T MaterializeUpdate<T>(T ephemeral)
{
return (T)MaterializeUpdate(typeof(T), ephemeral);
return MaterializeUpdateAsync<T>(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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -286,15 +320,15 @@ 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
if (mmremove != null)
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 });
}
}
Expand All @@ -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,
}
Expand All @@ -328,6 +362,5 @@ private void Merge (Type type, object ephemeral, object material)
}

}

}
}
14 changes: 7 additions & 7 deletions JSONAPI.EntityFramework/Http/ApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ protected override IQueryable<T> QueryableFactory(Core.IMaterializer materialize
return ((EntityFrameworkMaterializer)materializer).DbContext.Set<T>();
}

public override IList<T> Post(IList<T> postedObjs)
public override async Task<IList<T>> Post(IList<T> postedObjs)
{
var materializer = this.MaterializerFactory<EntityFrameworkMaterializer>();
List<T> materialList = new List<T>();
foreach (T postedObj in postedObjs)
{
DbContext context = materializer.DbContext;
var material = materializer.MaterializeUpdate(postedObj);
var material = await materializer.MaterializeUpdateAsync(postedObj);
if (context.Entry<T>(material).State == EntityState.Added)
{
context.SaveChanges();
Expand All @@ -61,28 +61,28 @@ public override IList<T> Post(IList<T> postedObjs)
return materialList;
}

public override IList<T> Put(string id, IList<T> putObjs)
public override async Task<IList<T>> Put(string id, IList<T> putObjs)
{
var materializer = this.MaterializerFactory<EntityFrameworkMaterializer>();
DbContext context = materializer.DbContext;
List<T> materialList = new List<T>();
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<EntityFrameworkMaterializer>();
DbContext context = materializer.DbContext;
T target = materializer.GetById<T>(id);
T target = await materializer.GetByIdAsync<T>(id);
context.Set<T>().Remove(target);
context.SaveChanges();
base.Delete(id);
await base.Delete(id);
}

protected override void Dispose(bool disposing)
Expand Down
18 changes: 12 additions & 6 deletions JSONAPI/Core/IMaterializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ namespace JSONAPI.Core
{
public interface IMaterializer
{
Task<T> GetByIdAsync<T>(params Object[] keyValues);
Task<object> GetByIdAsync(Type type, params Object[] keyValues);
Task<T> MaterializeAsync<T>(T ephemeral);
Task<object> MaterializeAsync(Type type, object ephemeral);
Task<T> MaterializeUpdateAsync<T>(T ephemeral);
Task<object> MaterializeUpdateAsync(Type type, object ephemeral);

T GetById<T>(params Object[] keyValues);
object GetById(Type type, params Object[] keyValues);
T Materialize<T>(T ephemeral);
object Materialize(Type type, object ephemeral);
T MaterializeUpdate<T>(T ephemeral);
object MaterializeUpdate(Type type, object ephemeral);
[Obsolete]T GetById<T>(params Object[] keyValues);
[Obsolete]object GetById(Type type, params Object[] keyValues);
[Obsolete]T Materialize<T>(T ephemeral);
[Obsolete]object Materialize(Type type, object ephemeral);
[Obsolete]T MaterializeUpdate<T>(T ephemeral);
[Obsolete]object MaterializeUpdate(Type type, object ephemeral);
}
}
19 changes: 10 additions & 9 deletions JSONAPI/Http/ApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -51,7 +52,7 @@ public virtual IQueryable<T> Get()
return es;
}

public virtual IEnumerable<T> Get(string id)
public virtual async Task<IEnumerable<T>> Get(string id)
{
IMaterializer materializer = MaterializerFactory();

Expand All @@ -67,7 +68,7 @@ public virtual IEnumerable<T> Get(string id)
}
foreach (string singleid in arrIds)
{
T hit = materializer.GetById<T>(singleid);
T hit = await materializer.GetByIdAsync<T>(singleid);
if (hit != null)
{
results.Add(hit);
Expand All @@ -85,29 +86,29 @@ public virtual IEnumerable<T> Get(string id)
/// </summary>
/// <param name="postedObj"></param>
/// <returns></returns>
public virtual IList<T> Post([FromBody] IList<T> postedObjs)
public virtual Task<IList<T>> Post([FromBody] IList<T> postedObjs)
{
foreach(T postedObj in postedObjs)
{
IMaterializer materializer = this.MaterializerFactory();
}
return postedObjs;
return Task.FromResult(postedObjs);
}

/// <summary>
/// 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.
/// </summary>
/// <param name="id"></param>
/// <param name="payload"></param>
/// <returns></returns>
public virtual IList<T> Put(string id, IList<T> putObjs)
public virtual async Task<IList<T>> Put(string id, IList<T> putObjs)
{
IMaterializer materializer = this.MaterializerFactory();
IList<T> materialList = new List<T>();
foreach (T putObj in putObjs)
{
materialList.Add(materializer.MaterializeUpdate<T>(putObj));
materialList.Add(await materializer.MaterializeUpdateAsync<T>(putObj));
}
return materialList;
}
Expand All @@ -116,9 +117,9 @@ public virtual IList<T> Put(string id, IList<T> putObjs)
/// A no-op method. This should be overriden in subclasses if Delete is to be supported.
/// </summary>
/// <param name="id"></param>
public virtual void Delete(string id)
public virtual Task Delete(string id)
{
return;
return Task.FromResult(0);
}
}
}