Skip to content

Commit

Permalink
Thread safety and multiple namespace support.
Browse files Browse the repository at this point in the history
In Domain.Core 2 places have been identified as shared states of multiple requests (hence threads), which needs thread safety.

In Domain.EntityFramework there's a limitation that entity types must come from a same namespace, it seems that limitation is unnecessary, since OData EDM could gracefully handle schema elements in multiple namespaces.
For entity container's namespace, in this fix the most popular one (which has most entity types) is chosen, if there's no entity type, namespace of the DbContext type is chosen, if DbContext type has no namespace, name of the DbContext type is chosen.
  • Loading branch information
rayao committed Nov 18, 2014
1 parent ebed566 commit 6f65070
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 23 deletions.
14 changes: 11 additions & 3 deletions src/Microsoft.Data.Domain.EntityFramework/Model/ModelProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,19 @@ public class ModelProducer : IModelProducer
.ObjectContext.MetadataWorkspace;
var namespaceName = efModel.GetItems<EntityType>(DataSpace.CSpace)
.Select(t => efModel.GetObjectSpaceType(t).NamespaceName)
.Distinct().SingleOrDefault();
.GroupBy(nameSpace => nameSpace)
.Select(group => new
{
NameSpace = group.Key,
Count = group.Count(),
})
.OrderByDescending(nsItem => nsItem.Count)
.Select(nsItem => nsItem.NameSpace)
.FirstOrDefault();
if (namespaceName == null)
{
// TODO: support multiple schemas
throw new NotSupportedException();
// When dbContext has not a namespace, just use its type name as namespace.
namespaceName = dbContext.GetType().Namespace ?? dbContext.GetType().Name;
}

var efEntityContainer = efModel.GetItems<
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.Data.Domain/DomainConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

Expand Down Expand Up @@ -76,7 +77,7 @@ public class DomainConfiguration : PropertyBag
{
private static readonly DomainConfiguration s_global = new DomainConfiguration();
private static readonly IDictionary<object, DomainConfiguration> s_configurations =
new Dictionary<object, DomainConfiguration>();
new ConcurrentDictionary<object, DomainConfiguration>();

private readonly IDictionary<Type, object> _singletons =
new Dictionary<Type, object>();
Expand Down
28 changes: 9 additions & 19 deletions src/Microsoft.Data.Domain/Model/DomainModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Annotations;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace Microsoft.Data.Domain.Model
{
Expand All @@ -30,7 +33,8 @@ namespace Microsoft.Data.Domain.Model
// to elements that are not supposed to be visible.
internal class DomainModel : IEdmModel
{
private IDictionary<string, DomainEntityContainer> _entityContainers;
private readonly Lazy<ConcurrentDictionary<string, DomainEntityContainer>> _entityContainers =
new Lazy<ConcurrentDictionary<string, DomainEntityContainer>>(LazyThreadSafetyMode.PublicationOnly);

public DomainModel(DomainConfiguration configuration, IEdmModel model)
{
Expand Down Expand Up @@ -204,22 +208,8 @@ private bool IsVocabularyAnnotatableVisible(
private DomainEntityContainer GetDomainEntityContainer(
IEdmEntityContainer entityContainer)
{
if (this._entityContainers == null)
{
this._entityContainers = new Dictionary<
string, DomainEntityContainer>();
}
DomainEntityContainer domainEntityContainer = null;
if (!this._entityContainers.TryGetValue(
entityContainer.FullName(),
out domainEntityContainer))
{
domainEntityContainer = new DomainEntityContainer(
this, entityContainer);
this._entityContainers.Add(
entityContainer.FullName(),
domainEntityContainer);
}
var domainEntityContainer = this._entityContainers.Value.GetOrAdd(
entityContainer.FullName(), name => new DomainEntityContainer(this, entityContainer));
return domainEntityContainer;
}
}
Expand Down

0 comments on commit 6f65070

Please sign in to comment.