Skip to content

Commit

Permalink
EntityModel reorg; Deferred loading progress. (Issue #1)
Browse files Browse the repository at this point in the history
  • Loading branch information
ToddThomson committed Aug 24, 2018
1 parent bf12431 commit c125b8b
Show file tree
Hide file tree
Showing 20 changed files with 345 additions and 227 deletions.
2 changes: 1 addition & 1 deletion Achilles.Entities.Sqlite/IEntitySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public interface IEntitySet
/// <returns></returns>
Type EntityType { get; }

IEnumerable<TSource> GetSource<TSource>( TSource source ) where TSource : class;
//IEnumerable<TSource> GetSource<TSource>( TSource source ) where TSource : class;
}
}
11 changes: 7 additions & 4 deletions Achilles.Entities.Sqlite/Linq/EntityReferenceOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace Achilles.Entities.Linq
{
public sealed class EntityReference<TEntity> : IEntityReference<TEntity>, IEntityReference
public sealed class EntityReference<TEntity> : IEntityReference<TEntity>, IEntityReference, IEntityReferenceSource
where TEntity : class
{
#region Private Fields
Expand All @@ -40,6 +40,8 @@ public EntityReference()

#region Public API

public bool IsLoaded => _isLoaded;

public TEntity Entity
{
get
Expand All @@ -54,10 +56,11 @@ public TEntity Entity
}
}

// TJT: Make a direct internal property (Source) reference through a compiled lambda expression
public void AttachSource( IEnumerable<TEntity> source )
public bool HasSource => (_source != null);

public void SetSource<TSource>( IEnumerable<TSource> source ) where TSource : class
{
_source = source;
_source = source as IEnumerable<TEntity>;
}

#endregion
Expand Down
4 changes: 1 addition & 3 deletions Achilles.Entities.Sqlite/Linq/IEntityReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@

#endregion

using System.Collections.Generic;

namespace Achilles.Entities.Linq
{
/// <summary>
/// Marker interface
/// </summary>
internal interface IEntityReference
{
//void AttachSource<TEntityRef>( IEnumerable<TEntityRef> source ) where TEntityRef: class;
// No API
}
}
2 changes: 1 addition & 1 deletion Achilles.Entities.Sqlite/Linq/IEntityReferenceOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Achilles.Entities.Linq
{
public interface IEntityReference<TEntity>
public interface IEntityReference<TEntity> where TEntity : class
{
/// <summary>
/// Gets the wrapped entity.
Expand Down
13 changes: 13 additions & 0 deletions Achilles.Entities.Sqlite/Linq/IEntityReferenceSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Achilles.Entities.Linq
{
internal interface IEntityReferenceSource
{
bool HasSource { get; }

void SetSource<TSource>( IEnumerable<TSource> source ) where TSource : class;
}
}
40 changes: 20 additions & 20 deletions Achilles.Entities.Sqlite/Modelling/EntityModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,47 @@ public class EntityModel : IEntityModel
{
#region Private Fields

private readonly EntityMappingCollection _entityMappings;
private DataContext _context;
private EntityMappingCollection _entityMappings;

#endregion

#region Constructor(s)

public EntityModel( EntityMappingCollection entityMappings )
public EntityModel( DataContext context )
{
_entityMappings = entityMappings ?? throw new ArgumentNullException( nameof( entityMappings ) );
_context = context;
_entityMappings = new EntityMappingCollection( this );
}

#endregion

#region Public API

/// <inheritdoc/>
public IReadOnlyCollection<IEntityMapping> EntityMappings => _entityMappings.Values as IReadOnlyCollection<IEntityMapping>;

//public IEntityMapping GetOrAddEntityMapping( Type entityType )
//{
// IEntityMapping mapping;

// if ( !_entityMappings.TryGetValue( entityType, out mapping ) )
// {
// var EntityMappingType = typeof( EntityMapping<> );
// var mapType = EntityMappingType.MakeGenericType( entityType );

// mapping = Activator.CreateInstance( mapType ) as IEntityMapping;

// _entityMappings[ entityType ] = mapping;
// }

// return mapping;
//}

/// <inheritdoc/>
public IEntityMapping GetEntityMapping<TEntity>() where TEntity : class
{
return GetEntityMapping( typeof( TEntity ) );
}

/// <inheritdoc/>
public IEntityMapping GetEntityMapping( Type entityType ) => _entityMappings.GetEntityMapping( entityType );

#endregion

#region Internal

internal IEntityMapping GetOrAddEntityMapping( Type entityType )
=> _entityMappings.GetOrAddEntityMapping( entityType );

internal void TryAddEntityMapping( Type entityType, IEntityMapping entityMapping )
=> _entityMappings.TryAddEntityMapping( entityType, entityMapping );

internal DataContext DataContext => _context;

#endregion
}
}
33 changes: 21 additions & 12 deletions Achilles.Entities.Sqlite/Modelling/EntityModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,28 @@
namespace Achilles.Entities.Modelling
{
/// <summary>
/// <see cref="IEntityModelBuilder"/> implementation of the fluent builder inteface for relational database modelling.
/// <see cref="IEntityModelBuilder"/> implementation of the fluent builder inteface for entity data modelling.
/// </summary>
public class EntityModelBuilder : IEntityModelBuilder
{
private DataContext _context;

#region Constructor(s)

/// <summary>
/// Constructs a new instance of <see cref="EntityModelBuilder"/>.
/// </summary>
public EntityModelBuilder()
{
EntityMappings = new EntityMappingCollection();
}

#endregion

#region Public Properties
#region Private Properties

/// <inheritdoc/>
private EntityMappingCollection EntityMappings { get; }
private EntityModel Model { get; set; }

//private EntityMappingCollection EntityMappings => Model.EntityMappings;

#endregion

Expand All @@ -47,7 +49,7 @@ public EntityModelBuilder()
/// <inheritdoc/>
public void Entity<TEntity>( Action<IEntityMappingBuilder<TEntity>> action ) where TEntity : class
{
var builder = new EntityMappingBuilder<TEntity>( EntityMappings );
var builder = new EntityMappingBuilder<TEntity>( Model );

action( builder );

Expand All @@ -57,25 +59,26 @@ public void Entity<TEntity>( Action<IEntityMappingBuilder<TEntity>> action ) whe
/// <inheritdoc />
public IEntityModel Build( DataContext context )
{
_context = context;

Model = new EntityModel( context );

// TJT: Should all entities be added in the user's data context constructor?
// What should happen if an entity is referenced during model building that is
// not in the context?

foreach ( var entitySetType in context.EntitySets.Keys )
{
EntityMappings.GetOrAddEntityMapping( entitySetType );
Model.GetOrAddEntityMapping( entitySetType );
}

context.OnModelBuilding( this );

// TODO: Model Validation...

// The model entity mappings have now been configured.
// Resolve Entity references and validate the model.

ResolveMappingsAndValidateModel();

return new EntityModel( EntityMappings );
return Model;
}

#endregion
Expand All @@ -86,12 +89,18 @@ private void AddEntityMapping<TEntity>( EntityMappingBuilder<TEntity> entityMapp
{
var EntityMapping = entityMappingBuilder.Build();

EntityMappings.TryAddEntityMapping( typeof( TEntity ), EntityMapping );
Model.TryAddEntityMapping( typeof( TEntity ), EntityMapping );
}

private void ResolveMappingsAndValidateModel()
{
foreach ( var entityMapping in Model.EntityMappings )
{
// TJT: Better name?
entityMapping.Compile();
}

// TODO: Model Validation...
}

#endregion
Expand Down
4 changes: 1 addition & 3 deletions Achilles.Entities.Sqlite/Modelling/IEntityModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ public interface IEntityModel
/// <returns>A read only collection of <see cref="IEntityMapping"/>.</returns>
IReadOnlyCollection<IEntityMapping> EntityMappings { get; }

//IEntityMapping GetOrAddEntityMapping( Type entityType );

/// <summary>
/// Gets an entity mapping by entity type.
/// </summary>
Expand All @@ -36,7 +34,7 @@ public interface IEntityModel
IEntityMapping GetEntityMapping( Type entityType );

/// <summary>
/// TODO
/// Gets an entity mapping by the generic TEntity type.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#region Copyright Notice

// Copyright (c) by Achilles Software, All rights reserved.
//
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Send questions regarding this copyright notice to: mailto:[email protected]

#endregion

#region Namespaces

using System.Reflection;

#endregion

namespace Achilles.Entities.Modelling.Mapping.Accessors
{
internal class ColumnAccessor<TEntity, TValue> : MemberAccessor<TEntity,TValue>
where TEntity : class
{
private readonly MemberInfo _columnInfo;

public ColumnAccessor( MemberInfo columnInfo )
: base( columnInfo )
{
_columnInfo = columnInfo;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#region Copyright Notice

// Copyright (c) by Achilles Software, All rights reserved.
//
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Send questions regarding this copyright notice to: mailto:[email protected]

#endregion

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Achilles.Entities.Modelling.Mapping.Accessors
{
internal class EntityCollectionAccessor<TEntity, TValue> : MemberAccessor<TEntity,TValue>
{
MemberInfo _entityCollectionInfo;

public EntityCollectionAccessor( MemberInfo entityReferenceInfo )
: base( entityReferenceInfo )
{
_entityCollectionInfo = entityReferenceInfo;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#region Copyright Notice

// Copyright (c) by Achilles Software, All rights reserved.
//
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Send questions regarding this copyright notice to: mailto:[email protected]

#endregion

#region Namespaces

using Achilles.Entities.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

#endregion

namespace Achilles.Entities.Modelling.Mapping.Accessors
{
internal class EntityReferenceAccessor<TEntity, TValue> : MemberAccessor<TEntity,TValue>
where TEntity : class
{
MemberInfo _entityReferenceInfo;
EntityReference<TEntity> _entityReference;

public EntityReferenceAccessor( MemberInfo entityReferenceInfo )
: base( entityReferenceInfo )
{
_entityReferenceInfo = entityReferenceInfo;
}

public Type EntityType => typeof( TEntity );

public override object GetValue( TEntity entity )
{
return base.GetValue( entity );
}

public override void SetValue( TEntity entity, object value )
{
// The base.GetValue gets the entityReference<> class
var entityReference = base.GetValue( entity ) as IEntityReferenceSource;

//Type entityReferencePropertyType = entityReferenceProperty.GetType();

//// Get the EntitySet<TEntity>
//var entityReference = entityReferencePropertyType.GetGenericArguments().First();
//var entitySet = _context.EntitySets[ entityReference ];


if ( !entityReference.HasSource )
{
entityReference.SetSource( value as IEnumerable<TEntity> );
}

//base.SetValue( entity, value );
}
}
}
Loading

0 comments on commit c125b8b

Please sign in to comment.