/// <summary> /// Constructor for an EntityContext object that uses the <see cref="ReflectionMappingProvider"/> /// to populate its entity type and property mappings. /// </summary> /// <remarks>This method is provided so that classes derived from <see cref="EntityContext"/> /// can be defined with additional properties that provide access to the types of entities that the context manages</remarks> protected EntityContext() { Mappings = new EntityMappingStore(); var rmp = new ReflectionMappingProvider(); rmp.AddMappingsForContext(Mappings, this); }
/// <summary> /// Attaches the object to the specified context /// </summary> /// <param name="context"></param> /// <param name="overwriteExisting"></param> public void Attach(EntityContext context, bool overwriteExisting = false) { if (context == null) { throw new ArgumentNullException("context"); } if (!(context is BrightstarEntityContext)) { throw new ArgumentException( String.Format("An object of type {0} can only be attached to a context that extends {1}", GetType().FullName, typeof(BrightstarEntityContext).FullName)); } if (IsAttached) { if (!context.Equals(_context)) { _context.UntrackObject(this); } } _context = context as BrightstarEntityContext; if (_identity == null) { AssertIdentity(); } if (DataObject == null && _identity != null) { DataObject = _context.GetDataObject(new Uri(_identity), false); var identityInfo = EntityMappingStore.GetIdentityInfo(GetType()); if (identityInfo != null && identityInfo.EnforceClassUniqueConstraint && !overwriteExisting) { _context.EnforceClassUniqueConstraint(_identity, EntityMappingStore.MapTypeToUris(GetType())); } foreach (var typeUri in EntityMappingStore.MapTypeToUris(GetType())) { if (!String.IsNullOrEmpty(typeUri)) { var typeDo = _context.GetDataObject(new Uri(typeUri), false); if (typeDo != null) { DataObject.AddProperty(Client.DataObject.TypeDataObject, typeDo); } } } } // if (DataObject != null) // { _context.TrackObject(this); // } if (_currentItemValues != null) { foreach (var propertyName in _currentItemValues.Keys.ToList()) { PropertyInfo p = GetType().GetProperty(propertyName); p.SetValue(this, _currentItemValues[propertyName], null); } _currentItemValues.Clear(); } }
/// <summary> /// Creates a new domain context /// </summary> /// <param name="mappings">The context type and property mappings</param> ///<param name="connectionString">The connection string that will be used to connect to an existing BrightstarDB store</param> ///<param name="enableOptimisticLocking">Optional parameter to override the optimistic locking configuration specified in the connection string</param> public BrightstarEntityContext(EntityMappingStore mappings, string connectionString, bool?enableOptimisticLocking = null) : base(mappings) { var cstr = new ConnectionString(connectionString); AssertStoreFromConnectionString(cstr); _store = OpenStore(cstr, enableOptimisticLocking); _trackedObjects = new Dictionary <string, List <BrightstarEntityObject> >(); }
/// <summary> /// Creates a new mapping store that copies its initial mappings from the specified source store /// </summary> /// <param name="source">The source <see cref="EntityMappingStore"/> from which mappings are copied</param> public EntityMappingStore(EntityMappingStore source) { _typeMappings = new Dictionary <Type, string>(source._typeMappings); _identifierPrefixes = new Dictionary <Type, string>(source._identifierPrefixes); _propertyHints = new Dictionary <PropertyInfo, PropertyHint>(source._propertyHints); _implMappings = new Dictionary <Type, Type>(source._implMappings); _identityProperties = new Dictionary <Type, PropertyInfo>(source._identityProperties); }
/// <summary> /// Creates a new domain context and connects to the store specified in the configuration connectionString. /// </summary> /// <param name="mappings">The context type and property mappings</param> public BrightstarEntityContext(EntityMappingStore mappings) : base(mappings) { var cstr = new ConnectionString(Configuration.ConnectionString); AssertStoreFromConnectionString(cstr); _store = OpenStore(cstr); _trackedObjects = new Dictionary <string, List <BrightstarEntityObject> >(); }
/// <summary> /// Creates a new domain context /// </summary> /// <param name="mappings">The context type and property mappings</param> ///<param name="connectionString">The connection string that will be used to connect to an existing BrightstarDB store</param> ///<param name="enableOptimisticLocking">Optional parameter to override the optimistic locking configuration specified in the connection string</param> /// <param name="updateGraphUri">OPTIONAL: The URI identifier of the graph to be updated with any new triples created by operations on the store. If /// not defined, the default graph in the store will be updated.</param> /// <param name="datasetGraphUris">OPTIONAL: The URI identifiers of the graphs that will be queried to retrieve entities and their properties. See /// the remarks below.</param> /// <param name="versionGraphUri">OPTIONAL: The URI identifier of the graph that contains version number statements for entities. /// If not defined, the <paramref name="updateGraphUri"/> will be used.</param> /// <remarks> /// <para>If <paramref name="datasetGraphUris"/> is null, then the context will query the graphs defined by /// <paramref name="updateGraphUri"/> and <paramref name="versionGraphUri"/> only. If all three parameters /// are null then the context will query across all graphs in the store.</para> /// </remarks> protected BrightstarEntityContext(EntityMappingStore mappings, string connectionString, bool?enableOptimisticLocking = null, string updateGraphUri = null, IEnumerable <string> datasetGraphUris = null, string versionGraphUri = null) : base(mappings) { var cstr = new ConnectionString(connectionString); AssertStoreFromConnectionString(cstr); _store = OpenStore(cstr, enableOptimisticLocking, updateGraphUri, datasetGraphUris, versionGraphUri); _trackedObjects = new Dictionary <string, List <BrightstarEntityObject> >(); }
/// <summary> /// Returns the RDF schema type for the specified entity interface or implementation type /// </summary> /// <param name="type">The entity interface or implementation type</param> /// <returns>The schema type URI for the entity type</returns> /// <exception cref="MappingNotFoundException">Raised if no mapping is found for <paramref name="type"/></exception> public string MapTypeToUri(Type type) { if (EntityMappingStore.IsMappedImplementation(type)) { return(EntityMappingStore.GetMappedInterfaceTypeUri(type)); } if (EntityMappingStore.IsKnownInterface(type)) { return(EntityMappingStore.GetMappedInterfaceTypeUri(EntityMappingStore.GetImplType(type))); } throw new MappingNotFoundException(type); }
/// <summary> /// Populates a <see cref="EntityMappingStore"/> with the entity mapping and property mapping information /// found on an entity implementation type /// </summary> /// <param name="mappingStore">The <see cref="EntityMappingStore"/> to be updated</param> /// <param name="mappedType">The entity implementation type to be processed</param> public void AddMappingsForType(EntityMappingStore mappingStore, Type mappedType) { var mappedTypeAssembly = mappedType.Assembly; AssemblyMappingInfo assemblyMappings; if (!_assemblyMappings.TryGetValue(mappedTypeAssembly.FullName, out assemblyMappings)) { assemblyMappings = GetAssemblyMappingInfo(mappedTypeAssembly); _assemblyMappings[mappedTypeAssembly.FullName] = assemblyMappings; } AddMappingsForType(mappingStore, assemblyMappings, mappedType); }
/// <summary> /// Processes the specified assembly for entity implementation types and adds all mapping information /// to the specified mapping store /// </summary> /// <param name="mappingStore">The <see cref="EntityMappingStore"/> to be updated</param> /// <param name="assembly">The assembly to be processed</param> public void AddMappingsForAssembly(EntityMappingStore mappingStore, Assembly assembly) { AssemblyMappingInfo assemblyMappings; if (!_assemblyMappings.TryGetValue(assembly.FullName, out assemblyMappings)) { assemblyMappings = GetAssemblyMappingInfo(assembly); _assemblyMappings[assembly.FullName] = assemblyMappings; } foreach (var t in assembly.GetTypes()) { AddMappingsForType(mappingStore, assemblyMappings, t); } }
/// <summary> /// Raises the PropertyChanged event /// </summary> /// <param name="propertyName">The name of the property that has been modified</param> protected virtual void OnPropertyChanged(string propertyName) { var identityInfo = EntityMappingStore.GetIdentityInfo(GetType()); if (identityInfo != null && identityInfo.KeyProperties != null && identityInfo.KeyProperties.Any(p => p.Name.Equals(propertyName))) { var newKey = GenerateEntityKey(); SetKey(newKey); } PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } }
private string GenerateEntityKey() { var identityCacheInfo = EntityMappingStore.GetIdentityInfo(GetType()); if (identityCacheInfo != null && identityCacheInfo.KeyProperties != null) { // Generate the key string var values = new object[identityCacheInfo.KeyProperties.Length]; for (var i = 0; i < identityCacheInfo.KeyProperties.Length; i++) { if (!_currentItemValues.TryGetValue(identityCacheInfo.KeyProperties[i].Name, out values[i])) { values[i] = identityCacheInfo.KeyProperties[i].GetValue(this, null); } } return(identityCacheInfo.KeyConverter.GenerateKey(values, identityCacheInfo.KeySeparator, GetType())); } return(Guid.NewGuid().ToString()); }
/// <summary> /// Processes a <see cref="EntityContext"/> instance to extract mapping details and uses them to populate /// a <see cref="EntityMappingStore"/> /// </summary> /// <param name="mappingStore">The <see cref="EntityMappingStore"/> to be populated</param> /// <param name="context">The <see cref="EntityContext"/> to be processed</param> public void AddMappingsForContext(EntityMappingStore mappingStore, EntityContext context) { var contextType = context.GetType(); var contextAssembly = contextType.Assembly; AssemblyMappingInfo assemblyMappings; if (!_assemblyMappings.TryGetValue(contextAssembly.FullName, out assemblyMappings)) { assemblyMappings = GetAssemblyMappingInfo(contextAssembly); _assemblyMappings[contextAssembly.FullName] = assemblyMappings; } var queryableGeneric = typeof(IQueryable <object>).GetGenericTypeDefinition(); foreach (var p in contextType.GetProperties()) { if (p.PropertyType.IsGenericType && queryableGeneric.IsAssignableFrom(p.PropertyType.GetGenericTypeDefinition())) { var genericParam = p.PropertyType.GetGenericArguments()[0]; AddMappingsForType(mappingStore, genericParam); } } }
/// <summary> /// Returns true if <paramref name="o"/> is an instance of one of the entity implementation types known to this context /// </summary> /// <param name="o">The object to be checked</param> /// <returns>True if the object is an instance of a known entity implementation type, false otherwise</returns> public bool IsOfMappedType(object o) { return(EntityMappingStore.IsKnownInterface(o.GetType()) || EntityMappingStore.IsMappedImplementation(o.GetType())); }
/// <summary> /// Returns the entity implementation type for an entity interface type /// </summary> /// <param name="interfaceType">The entity interface type</param> /// <returns>The mapped entity implementation type, or <paramref name="interfaceType"/> if no mapping is found</returns> public Type GetImplType(Type interfaceType) { return(EntityMappingStore.GetImplType(interfaceType)); }
/// <summary> /// Constructor for an EntityContext object /// </summary> /// <param name="mappings">The store providing type and property mappings to use in LINQ to SPARQL queries</param> protected EntityContext(EntityMappingStore mappings) { Mappings = mappings; }
/// <summary> /// Creates a new domain context /// </summary> /// <param name="mappings">The context type and property mappings</param> /// <param name="store">The Brightstar store that manages the data</param> protected BrightstarEntityContext(EntityMappingStore mappings, IDataObjectStore store) : base(mappings) { _store = store; _trackedObjects = new Dictionary <string, List <BrightstarEntityObject> >(); }
internal string GetIdentityBase() { var identityCacheInfo = EntityMappingStore.GetIdentityInfo(GetType()); return(identityCacheInfo.BaseUri); }
private static void AddMappingsForType(EntityMappingStore mappingStore, AssemblyMappingInfo assemblyMappingInfo, Type mappedType) { var entityAttribute = mappedType.GetCustomAttributes(typeof(EntityAttribute), false).OfType <EntityAttribute>(). FirstOrDefault(); if (entityAttribute != null) { var entityTypeIdentifier = entityAttribute.Identifier ?? GetImplTypeName(mappedType); mappingStore.SetTypeMapping(mappedType, assemblyMappingInfo.ResolveIdentifier(entityTypeIdentifier)); var identityProperty = GetIdentityProperty(mappedType); if (identityProperty != null) { var identifierAttr = identityProperty.GetCustomAttributes(typeof(IdentifierAttribute), true).Cast <IdentifierAttribute>().FirstOrDefault(); var identityInfo = GetIdentityInfo(assemblyMappingInfo, mappedType, identityProperty, identifierAttr); mappingStore.SetIdentityInfo(mappedType, identityInfo); mappingStore.SetPropertyHint(identityProperty, new PropertyHint(PropertyMappingType.Id)); } foreach (var p in mappedType.GetProperties()) { if (p.Equals(identityProperty)) { // Identity property is already mapped (above) continue; } foreach (var attr in p.GetCustomAttributes(false)) { /* * if (attr is IdentifierAttribute) * { * mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.Address)); * var idAttr = attr as IdentifierAttribute; * if (idAttr.BaseAddress != null) * { * mappingStore.SetIdentifierPrefix(mappedType, assemblyMappingInfo.ResolveIdentifier(idAttr.BaseAddress)); * } * } * else*/ if (attr is PropertyTypeAttribute) { var propertyUri = assemblyMappingInfo.ResolveIdentifier((attr as PropertyTypeAttribute).Identifier); mappingStore.SetPropertyHint(p, IsResource(p.PropertyType) ? new PropertyHint(PropertyMappingType.Arc, propertyUri) : new PropertyHint(PropertyMappingType.Property, propertyUri)); } else if (attr is InversePropertyTypeAttribute) { var propertyUri = assemblyMappingInfo.ResolveIdentifier((attr as InversePropertyTypeAttribute).Identifier); var targetType = p.PropertyType; if (targetType.IsGenericType) { targetType = targetType.GetGenericArguments().First(); } if (targetType.GetCustomAttributes(typeof(EntityAttribute), false).Any()) { mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.InverseArc, propertyUri)); } else { throw new ReflectionMappingException( String.Format( "The property '{0}' on type '{1}' is marked with the InverseProperty attribute but its referenced type ('{2}') is not marked with a Entity attribute.", p.Name, mappedType.FullName, p.PropertyType.FullName)); } } else if (attr is InversePropertyAttribute) { var inversePropertyAttr = attr as InversePropertyAttribute; var targetType = p.PropertyType; if (targetType.IsGenericType) { targetType = targetType.GetGenericArguments().First(); } if (!targetType.GetCustomAttributes(typeof(EntityAttribute), true).Any()) { throw new ReflectionMappingException( String.Format( "The type of property '{0}' on interface '{1}' is not marked with an Entity attribute.", p.Name, mappedType.FullName)); } var forwardProperty = targetType.GetProperty(inversePropertyAttr.InversePropertyName); if (forwardProperty == null) { throw new ReflectionMappingException(String.Format("The property '{0}' does not exist on type '{1}'.", inversePropertyAttr.InversePropertyName, targetType.FullName)); } var inversePropertyTypeUri = assemblyMappingInfo.ResolveIdentifier(GetForwardPropertyTypeUri(forwardProperty, p)); mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.InverseArc, inversePropertyTypeUri)); } } if (mappingStore.GetPropertyHint(p) == null) { // If there has been no mapping at all, then we create a property mapping var propertyName = Char.ToLowerInvariant(p.Name[0]) + p.Name.Substring(1); var propertyUri = assemblyMappingInfo.ResolveIdentifier(propertyName); mappingStore.SetPropertyHint(p, IsResource(p.PropertyType) ? new PropertyHint(PropertyMappingType.Arc, propertyUri) : new PropertyHint(PropertyMappingType.Property, propertyUri)); } } } }