Пример #1
0
    public static void GetIsCurrentEntityMany(Entity prevEntity, Entity CurEntity, out bool?isMany)
    {
        EntityRelationship rel     = null;
        EntityProperty     relProp = null;

        if (
            prevEntity.EntityProperties.SelectMany(x => x.ChildRelationships)
            .FirstOrDefault(x => x.ChildProperty.Entity == CurEntity) != null)
        {
            rel = prevEntity.EntityProperties.SelectMany(x => x.ChildRelationships)
                  .FirstOrDefault(x => x.ChildProperty.Entity == CurEntity);
            relProp = rel.ChildProperty;
            isMany  = relProp.DataProperties.All(x => x.ModelType.Name == "ForeignKey") &&
                      !(relProp.DataProperties.All(x => x.ModelType.Name == "EntityId"));
            return;
        }
        else if (
            prevEntity.EntityProperties.SelectMany(x => x.ParentRelationships)
            .FirstOrDefault(x => x.ParentProperty.Entity == CurEntity) != null)
        {
            rel = prevEntity.EntityProperties.SelectMany(x => x.ParentRelationships)
                  .FirstOrDefault(x => x.ParentProperty.Entity == CurEntity);
            relProp = rel.ParentProperty;
            isMany  = relProp.DataProperties.All(x => x.ModelType.Name == "ForeignKey") &&
                      !(relProp.DataProperties.All(x => x.ModelType.Name == "EntityId"));
            return;
        }

        isMany = null;
    }
Пример #2
0
        public static async Task <string> CreateRelationship([ActivityTrigger] EntityRelationship entityRelationship, TraceWriter log)
        {
            await GraphHelper.CreateRelationship(entityRelationship);

            log.Info($"Added: {entityRelationship.FromVertex.Name}, {entityRelationship.Relationship}, To: {entityRelationship.ToVertex.Name}");
            return($"Added: {entityRelationship.FromVertex.Name}, {entityRelationship.Relationship}, To: {entityRelationship.ToVertex.Name}");
        }
Пример #3
0
        /// <summary>
        /// Construct an ER master
        /// </summary>
        public EntityRelationshipMaster(Entity master, Entity local, EntityRelationship relationship)
        {
            this.OriginalHolderKey = relationship.HolderKey;
            this.OriginalTargetKey = relationship.TargetEntityKey;
            this.Key = relationship.Key; // HACK: This is just for the FHIR layer to track RP
            this.RelationshipRoleKey = relationship.RelationshipRoleKey;
            this.RelationshipTypeKey = relationship.RelationshipTypeKey;
            this.ClassificationKey   = relationship.ClassificationKey;
            this.SourceEntityKey     = relationship.SourceEntityKey;
            this.TargetEntityKey     = relationship.TargetEntityKey;
            this.Strength            = relationship.Strength;

            if (this.SourceEntityKey == local.Key &&
                this.RelationshipTypeKey != MdmConstants.OriginalMasterRelationship &&
                this.RelationshipTypeKey != MdmConstants.CandidateLocalRelationship &&
                this.RelationshipTypeKey != MdmConstants.MasterRecordRelationship)
            {
                this.SourceEntityKey = master.Key;
            }
            else if (this.TargetEntityKey == local.Key &&
                     this.RelationshipTypeKey != MdmConstants.MasterRecordOfTruthRelationship)
            {
                this.TargetEntityKey = master.Key;
            }

            // Does the target point at a local which has a master? If so, we want to synthesize the
            var targetMaster = this.GetTargetAs <Entity>().GetRelationships().FirstOrDefault(mr => mr.RelationshipTypeKey == MdmConstants.MasterRecordRelationship);

            if (targetMaster != null)
            {
                this.TargetEntityKey = targetMaster.TargetEntityKey;
            }
            this.m_annotations.Clear();
        }
Пример #4
0
        public static void GenerateStock(String[] args)
        {
            ApplicationServiceContext.Current = ApplicationContext.Current;
            //cp.Repository = new SeederProtocolRepositoryService();
            ApplicationContext.Current.Start();
            var            idp = ApplicationContext.Current.GetService <IDataPersistenceService <Place> >();
            WaitThreadPool wtp = new WaitThreadPool();
            var            mat = ApplicationContext.Current.GetService <IDataPersistenceService <Material> >().Query(o => o.ClassConceptKey == EntityClassKeys.Material, AuthenticationContext.SystemPrincipal);

            Console.WriteLine("Database has {0} materials", mat.Count());

            int tr = 0, ofs = 0;

            Console.WriteLine("Querying for places");
            var results = idp.Query(o => o.ClassConceptKey == EntityClassKeys.ServiceDeliveryLocation, ofs, 1000, AuthenticationContext.SystemPrincipal, out tr);

            Console.WriteLine("Will create fake stock for {0} places", tr);
            var r = new Random();

            while (ofs < tr)
            {
                foreach (var p in results)
                {
                    wtp.QueueUserWorkItem((parm) =>
                    {
                        try
                        {
                            Place target = parm as Place;
                            Console.WriteLine("Starting seeding for {0} currently {1} relationships", target.Names.FirstOrDefault().Component.FirstOrDefault().Value, target.Relationships.Count);

                            // Add some stock!!! :)
                            foreach (var m in mat)
                            {
                                var mmats = m.Relationships.Where(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Instance).OrderBy(o => r.Next()).FirstOrDefault();
                                Console.WriteLine("Selected {0} out of {1} materials", mmats, m.Relationships.Count);
                                var rdp = ApplicationContext.Current.GetService <IDataPersistenceService <EntityRelationship> >();
                                if (mmats != null)
                                {
                                    var er = new EntityRelationship(EntityRelationshipTypeKeys.OwnedEntity, mmats.TargetEntityKey)
                                    {
                                        Quantity = r.Next(0, 100), SourceEntityKey = target.Key, EffectiveVersionSequenceId = target.VersionSequence
                                    };
                                    Console.WriteLine("{0} > {1} {2}", target.Names.FirstOrDefault().Component.FirstOrDefault().Value, er.Quantity, m.Names.FirstOrDefault().Component.FirstOrDefault().Value);
                                    rdp.Insert(er, AuthenticationContext.SystemPrincipal, TransactionMode.Commit);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                        }
                    }, p);
                }
                wtp.WaitOne();
                ofs    += 25;
                results = idp.Query(o => o.ClassConceptKey == EntityClassKeys.ServiceDeliveryLocation, ofs, 25, AuthenticationContext.SystemPrincipal, out tr);
            }
        }
Пример #5
0
        private static void DeleteLinkTable(StringBuilder sb, EntityRelationship link)
        {
            var linkTable = new CSharpClass
            {
                Name = $"{link.First.Name}_{link.Second.Name}"
            };

            DeleteTable(sb, linkTable);
        }
        /// <summary>
        /// Saves the specified data
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns>TModel.</returns>
        /// <exception cref="System.InvalidOperationException">Thrown if the persistence service is not found.</exception>
        public EntityRelationship Save(EntityRelationship data)
        {
            // force set the version sequence
            if (data.EffectiveVersionSequenceId == null)
            {
                data.EffectiveVersionSequenceId = this.Get <Entity>(data.SourceEntityKey.Value, Guid.Empty)?.VersionSequence;
            }

            return(base.Save(data));
        }
        /// <summary>
        /// Creates an entity relationship.
        /// </summary>
        /// <param name="sourceKey">The source key.</param>
        /// <param name="targetKey">The target key.</param>
        /// <param name="relationshipType">Type of the relationship.</param>
        /// <param name="quantity">The quantity.</param>
        /// <returns>Returns the created entity relationship.</returns>
        public EntityRelationship Create(Guid sourceKey, Guid targetKey, Guid relationshipType, uint quantity)
        {
            var entityRelationship = new EntityRelationship(relationshipType, targetKey)
            {
                SourceEntityKey = sourceKey,
                Quantity        = Convert.ToInt32(quantity)
            };

            return(this.Client.Create(entityRelationship));
        }
Пример #8
0
        /// <summary>
        /// Maps the entity relationship organization contact.
        /// </summary>
        /// <param name="contact">The contact.</param>
        /// <returns>Returns the mapped entity relationship from an organization contact instance.</returns>
        private static EntityRelationship MapEntityRelationshipOrganizationContact(organizationContact contact, CsdOptions options)
        {
            EntityRelationship entityRelationship = null;

            if (contact.Item.GetType() == typeof(uniqueID))
            {
                var csdProvider = contact.Item as uniqueID;

                var provider = GetOrCreateEntity <Provider>(csdProvider.entityID, options.EntityUidAuthority, options);

                entityRelationship = new EntityRelationship(EntityRelationshipTypeKeys.Contact, provider);
            }
            else if (contact.Item.GetType() == typeof(person))
            {
                var csdPerson = contact.Item as person;

                var personService = ApplicationContext.Current.GetService <IPersonRepositoryService>();

                // TODO: fix to search the person by address, name, date of birth, and gender, to find an existing person before creating a new one
                // we are creating a new person here, because the person class in CSD doesn't have an entityID
                // property for us to use to lookup the person to see if they exist.
                var person = new Person
                {
                    Addresses = csdPerson.address?.Select(a => MapEntityAddress(a, new Uri(AddressTypeCodeSystem))).ToList() ?? new List <EntityAddress>(),
                    Key       = Guid.NewGuid()
                };

                if (csdPerson.dateOfBirthSpecified)
                {
                    person.DateOfBirth = csdPerson.dateOfBirth;
                }

                // map names
                if (csdPerson.name?.Any() == true)
                {
                    person.Names.RemoveAll(c => c.NameUseKey == NameUseKeys.OfficialRecord);
                    person.Names.AddRange(csdPerson.name.Select(c => MapEntityNamePerson(NameUseKeys.OfficialRecord, c)));
                }

                // map telecommunications
                if (csdPerson.contactPoint?.Any() == true)
                {
                    person.Telecoms.RemoveAll(c => c.AddressUseKey == TelecomAddressUseKeys.Public);
                    person.Telecoms.AddRange(csdPerson.contactPoint?.Select(c => MapContactPoint(TelecomAddressUseKeys.Public, c)));
                }

                entityRelationship = new EntityRelationship(EntityRelationshipTypeKeys.Contact, person);
            }
            else
            {
                ShowErrorOnNotFound($"Error, {emergencyMessage} {nameof(organizationContact.Item)} is not of type: {nameof(person)} or {nameof(uniqueID)}");
            }

            return(entityRelationship);
        }
Пример #9
0
        private void ApplyForeignKeyChanges <TRelatedEntity>(EntityRelationship relationship, IEnumerable <TEntity> entities) where TRelatedEntity : class
        {
            var definition = EntityMapping.GetOrCreateDefinition(typeof(TRelatedEntity));
            var defaultId  = definition.GetDefaultId();

            foreach (var entity in entities)
            {
                var relatedEntity = (TRelatedEntity)relationship.NavigationProperty.GetValue(entity);
                var entityId      = relatedEntity == null ? defaultId : definition.GetIdValue(relatedEntity);
                relationship.IdProperty.SetValue(entity, entityId);
            }
        }
Пример #10
0
 private void UpdateAllEntitiesKnowledge(
     EntityRelationship <GameEntity> levelEntitiesToLevelRelationship,
     EntityMatcher <GameEntity> matcher,
     LevelComponent level,
     GameManager manager)
 {
     // TODO: Perf: use interval tree to only get the entities and knowledge within sense range
     foreach (var levelEntity in levelEntitiesToLevelRelationship[level.EntityId])
     {
         UpdateEntityKnowledge(levelEntity, matcher, manager, level: level);
     }
 }
        public void TestEquality( )
        {
            var r      = new EntityRelationship <IEntity>(null);
            var entity = new Entity(new ActivationData( ));

            Assert.AreEqual(r, new EntityRelationship <IEntity>(null));
            Assert.AreNotEqual(r, new EntityRelationship <IEntity>(entity));

            r = new EntityRelationship <IEntity>(entity);
            Assert.AreNotEqual(r, new EntityRelationship <IEntity>(null));
            Assert.AreEqual(r, new EntityRelationship <IEntity>(entity));
        }
Пример #12
0
        private void CreateForeignKey(StringBuilder sb, EntityRelationship link)
        {
            // loop relationship
            if (link.First.Id == link.Second.Id)
            {
                // Note:  GetForeignKeyMember will append 'Id'
                foreach (var suppFk in SupportedLoopForeignKeys)
                {
                    var fkLoop = GetForeignKeyMember((CSharpClass)link.First, suppFk.ToLowerInvariant());
                    if (fkLoop != null)
                    {
                        var pk = GetPrimaryKeyMember((CSharpClass)link.First);
                        CreateForeignKey(sb, link.First.Name, link.First, link.First, fkLoop.Name, pk.Name);
                        return;
                    }
                }

                // should never get here as should have passed pre-flight checks
                var fileName = Path.ChangeExtension(Model.Name, ".sql");
                var errMsg   = $"Unknown error generating loop relationship:  [{link.First.Name}] <---> [{link.Second.Name}]";
                sb.AppendLine($"-- {errMsg}");
                throw new FileGenerationException(fileName, errMsg);
            }

            // create link tables
            if ((link.StartMultiplicity == MultiplicityType.ZeroOrMany || link.StartMultiplicity == MultiplicityType.OneOrMany) &&
                (link.EndMultiplicity == MultiplicityType.ZeroOrMany || link.EndMultiplicity == MultiplicityType.OneOrMany))
            {
                sb.AppendLine();
                sb.AppendLine($"-- generate link table: [{link.First.Name}] >+--+< [{link.Second.Name}]");
                CreateLinkTable(sb, link);
                sb.AppendLine();
                return;
            }

            // [First] --> [Second]
            var fk1 = GetForeignKeyMember((CSharpClass)link.Second, link.First.Name);

            if (fk1 != null)
            {
                var pk1 = GetPrimaryKeyMember((CSharpClass)link.First);
                CreateForeignKey(sb, link.Second.Name, link.First, link.Second, fk1.Name, pk1.Name);
            }

            // [Second] --> [First]
            var fk2 = GetForeignKeyMember((CSharpClass)link.First, link.Second.Name);

            if (fk2 != null)
            {
                var pk2 = GetPrimaryKeyMember((CSharpClass)link.Second);
                CreateForeignKey(sb, link.First.Name, link.Second, link.First, fk2.Name, pk2.Name);
            }
        }
Пример #13
0
        public async Task <List <EntityRelationship> > PushRelatedArtist(string artistId, List <Artist> relatedArtists)
        {
            Artist baseArtist = await GetArtist(artistId);

            CanonicalService          canonicalService       = new CanonicalService();
            List <EntityRelationship> entityRelationshipList = new List <EntityRelationship>();

            try
            {
                RdostrId baseArtistRdo   = canonicalService.GetArtistId(baseArtist.name);
                string   baseArtistId    = $"{baseArtist.name}:{baseArtistRdo.Id}";
                JObject  baseArtistProps = JObject.FromObject(new {
                    Properties = new
                    {
                        type       = "artist",
                        spotifyid  = baseArtist.spotify.id,
                        spotifyuri = baseArtist.spotify.uri,
                        images     = baseArtist.images[0]
                    }
                });
                Entity baseArtistEntity = new Entity(baseArtistId, baseArtist.name, baseArtistProps);
                foreach (Artist relatedArtist in relatedArtists)
                {
                    RdostrId relatedArtistRdo   = canonicalService.GetArtistId(relatedArtist.name);
                    string   relatedArtistId    = $"{relatedArtist.name}:{relatedArtistRdo.Id}";
                    JObject  relatedArtistProps = JObject.FromObject(new
                    {
                        Properties = new
                        {
                            type       = "artist",
                            spotifyid  = relatedArtist.spotify.id,
                            spotifyuri = relatedArtist.spotify.uri,
                            images     = relatedArtist.images[0]
                        }
                    });
                    Entity             relatedEntity      = new Entity(relatedArtistId, relatedArtist.name, relatedArtistProps);
                    EntityRelationship entityRelationship = new EntityRelationship
                    {
                        FromVertex       = baseArtistEntity,
                        Relationship     = "related",
                        RelationshipDate = DateTime.UtcNow,
                        ToVertex         = relatedEntity
                    };
                    entityRelationshipList.Add(entityRelationship);
                }
            }
            catch
            {
            }

            return(entityRelationshipList);
        }
Пример #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EntityRelationshipModel" /> class.
        /// </summary>
        /// <param name="entityRelationship">The entity relationship.</param>
        public EntityRelationshipModel(EntityRelationship entityRelationship) : this(entityRelationship.Key.Value, entityRelationship.SourceEntityKey.Value, entityRelationship.TargetEntityKey.Value)
        {
            this.RelationshipType = entityRelationship.RelationshipTypeKey?.ToString() ?? Constants.NotApplicable;

            this.RelationshipTypeName = entityRelationship.RelationshipType != null?string.Join(" ", entityRelationship.RelationshipType.ConceptNames.Select(c => c.Name)) : Constants.NotApplicable;

            this.SourceName = entityRelationship.SourceEntity != null?string.Join(" ", entityRelationship.SourceEntity.Names.SelectMany(n => n.Component).Select(c => c.Value)) : Constants.NotApplicable;

            this.SourceTypeConcept = entityRelationship.SourceEntity?.TypeConcept != null?string.Join(" ", entityRelationship.SourceEntity.TypeConcept.ConceptNames.Select(c => c.Name)) : Constants.NotApplicable;

            this.TargetName = entityRelationship.TargetEntity != null?string.Join(" ", entityRelationship.TargetEntity.Names.SelectMany(n => n.Component).Select(c => c.Value)) : Constants.NotApplicable;

            this.TargetTypeConcept = entityRelationship.TargetEntity?.TypeConcept != null?string.Join(" ", entityRelationship.TargetEntity.TypeConcept.ConceptNames.Select(c => c.Name)) : Constants.NotApplicable;
        }
Пример #15
0
        private Variables getVariables(EntityRelationship relationship)
        {
            switch (relationship)
            {
            case EntityRelationship.Self: return(Variables);

            case EntityRelationship.Owner: return(Owner != null ? Owner.Variables : null);

            case EntityRelationship.Subject: return(Subject != null ? Subject.Variables : null);

            case EntityRelationship.Target: return((Targets.Length > 0) ? Targets[0].Variables : null);

            default: throw new InvalidProgramException("EntityRelationship " + relationship + " not handled");
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="EntityRelationshipViewModel" /> class.
        /// </summary>
        /// <param name="entityRelationship">The entity relationship.</param>
        /// <param name="isInverse">if set to <c>true</c> the relationship is inverse, which means that the target of the relationship is the entity instead of the source.</param>
        public EntityRelationshipViewModel(EntityRelationship entityRelationship, bool isInverse = false)
        {
            this.Id        = entityRelationship.Key.Value;
            this.IsInverse = isInverse;
            this.Quantity  = entityRelationship.Quantity;

            this.RelationshipTypeName = entityRelationship.RelationshipType != null?string.Join(" ", entityRelationship.RelationshipType.ConceptNames.Select(c => c.Name)) : Constants.NotApplicable;

            this.SourceName = entityRelationship.SourceEntity != null?string.Join(" ", entityRelationship.SourceEntity.Names.SelectMany(n => n.Component).Select(c => c.Value)) : Constants.NotApplicable;

            this.SourceTypeConcept = entityRelationship.SourceEntity?.TypeConcept != null?string.Join(" ", entityRelationship.SourceEntity.TypeConcept.ConceptNames.Select(c => c.Name)) : Constants.NotApplicable;

            this.TargetName = entityRelationship.TargetEntity != null?string.Join(" ", entityRelationship.TargetEntity.Names.SelectMany(n => n.Component).Select(c => c.Value)) : Constants.NotApplicable;

            this.TargetTypeConcept = entityRelationship.TargetEntity?.TypeConcept != null?string.Join(" ", entityRelationship.TargetEntity.TypeConcept.ConceptNames.Select(c => c.Name)) : Constants.NotApplicable;
        }
Пример #17
0
#pragma warning disable CRR0026 // Unused member - used via Reflection
        private void CommitRelationship <TRelatedEntity>(EntityRelationship relationship, IEnumerable <TEntity> entities) where TRelatedEntity : class
        {
            var collection = BuildRelatedEntityCollection <TRelatedEntity>(relationship, entities);

            if (collection.Any())
            {
                var dbSet = new MongoDbSet <TRelatedEntity>();
                dbSet.SetConnection(Connection);
                dbSet.AddRange(collection);
                dbSet.SaveChanges();
            }

            if (!relationship.IsCollection)
            {
                ApplyForeignKeyChanges <TRelatedEntity>(relationship, entities);
            }
        }
Пример #18
0
#pragma warning restore CRR0026 // Unused member - used via Reflection

#pragma warning disable CRR0026 // Unused member - used via Reflection
        private async Task CommitRelationshipAsync <TRelatedEntity>(EntityRelationship relationship, IEnumerable <TEntity> entities, CancellationToken cancellationToken) where TRelatedEntity : class
        {
            var collection = BuildRelatedEntityCollection <TRelatedEntity>(relationship, entities);

            cancellationToken.ThrowIfCancellationRequested();

            if (collection.Any())
            {
                var dbSet = new MongoDbSet <TRelatedEntity>();
                dbSet.SetConnection(Connection);
                dbSet.AddRange(collection);
                await dbSet.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }

            if (!relationship.IsCollection)
            {
                ApplyForeignKeyChanges <TRelatedEntity>(relationship, entities);
            }
        }
Пример #19
0
        private static async Task CheckOrCreateRelationship(EntityRelationship input)
        {
            try
            {
                //g.V('default-user').outE('likes').inV().has('id', 'metallica:c6b5b6413f293fce96539c41e704b5a2')
                var gremlinQuery = $@"g.V('{input.FromVertex.Id}').outE('{input.Relationship}').inV().has('id', '{input.ToVertex.Id}')";
                var likes        = await RunDocumentQuery(gremlinQuery.ToString());

                if (likes.Count == 0)
                {
                    var gremlinInsert = $@"g.V('{input.FromVertex.Id}').addE('{input.Relationship}').to(g.V('{input.ToVertex.Id}'))";
                    await RunDocumentQuery(gremlinInsert.ToString());
                }
            }
            catch (DocumentClientException ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }
Пример #20
0
        public async Task Run_CreateRelationshipwithSpecial_DoesNotError()
        {
            // initialise

            // arrange
            Entity             testUser           = TestHelper.NewEntity("testUser", "user");
            Entity             testArtist         = TestHelper.NewEntity("incubus:373c591c05ed02146136d1ceb704191f", "Incubus 's test special", "artist");
            EntityRelationship entityRelationship = new EntityRelationship();

            entityRelationship.FromVertex       = testUser;
            entityRelationship.ToVertex         = testArtist;
            entityRelationship.Relationship     = "likes";
            entityRelationship.RelationshipDate = DateTime.UtcNow;
            List <EntityRelationship> entityRelationships = new List <EntityRelationship>();

            entityRelationships.Add(entityRelationship);

            // act
            try
            {
                var mockMsgString = JsonConvert.SerializeObject(entityRelationships);
                await GraphHelper.CreateRelationship(entityRelationship);


                // assert
            }
            catch
            {
                throw;
            }
            finally
            {
                // teardown
                var cleanupFrom = await GraphHelper.RemoveVertex(testUser.Id);

                var cleanupTo = await GraphHelper.RemoveVertex(testArtist.Id);
            }
        }
Пример #21
0
        private static void CreateLinkTable(StringBuilder sb, EntityRelationship link)
        {
            var linkTable = new CSharpClass
            {
                Name = $"{link.First.Name}_{link.Second.Name}"
            };

            var pk1     = GetPrimaryKeyMember((CSharpClass)link.First);
            var firstId = linkTable.AddProperty();

            firstId.Name = $"{link.First.Name}Id";
            firstId.Type = pk1.Type;

            var pk2      = GetPrimaryKeyMember((CSharpClass)link.Second);
            var secondId = linkTable.AddProperty();

            secondId.Name = $"{link.Second.Name}Id";
            secondId.Type = pk2.Type;

            CreateTable(sb, linkTable);

            CreateForeignKey(sb, linkTable.Name, link.First, link.Second, firstId.Name, pk1.Name);
            CreateForeignKey(sb, linkTable.Name, link.Second, link.First, secondId.Name, pk2.Name);
        }
Пример #22
0
        /// <summary>
        /// Gets the manufactured material from the specified trade item
        /// </summary>
        public ManufacturedMaterial GetManufacturedMaterial(TransactionalTradeItemType tradeItem, bool createIfNotFound = false)
        {
            if (tradeItem == null)
            {
                throw new ArgumentNullException("tradeItem", "Trade item must have a value");
            }
            else if (String.IsNullOrEmpty(tradeItem.gtin))
            {
                throw new ArgumentException("Trade item is missing GTIN", "tradeItem");
            }


            var oidService = ApplicationContext.Current.GetService <IOidRegistrarService>();
            var gtin       = oidService.GetOid("GTIN");

            // Lookup material by lot number / gtin
            int tr = 0;
            var lotNumberString         = tradeItem.transactionalItemData[0].lotNumber;
            ManufacturedMaterial retVal = this.m_materialRepository.FindManufacturedMaterial(m => m.Identifiers.Any(o => o.Value == tradeItem.gtin && o.Authority.DomainName == "GTIN") && m.LotNumber == lotNumberString, 0, 1, out tr).FirstOrDefault();

            if (retVal == null && createIfNotFound)
            {
                var additionalData = tradeItem.transactionalItemData[0];
                if (!additionalData.itemExpirationDateSpecified)
                {
                    throw new InvalidOperationException("Cannot auto-create material, expiration date is missing");
                }

                // Material
                retVal = new ManufacturedMaterial()
                {
                    Key         = Guid.NewGuid(),
                    LotNumber   = additionalData.lotNumber,
                    Identifiers = new List <EntityIdentifier>()
                    {
                        new EntityIdentifier(new AssigningAuthority(gtin.Mnemonic, gtin.Name, gtin.Oid), tradeItem.gtin)
                    },
                    ExpiryDate = additionalData.itemExpirationDate,
                    Names      = new List <EntityName>()
                    {
                        new EntityName(NameUseKeys.Assigned, tradeItem.tradeItemDescription.Value)
                    },
                    StatusConceptKey   = StatusKeys.Active,
                    QuantityConceptKey = Guid.Parse("a4fc5c93-31c2-4f87-990e-c5a4e5ea2e76"),
                    Quantity           = 1
                };

                // Store additional identifiers
                if (tradeItem.additionalTradeItemIdentification != null)
                {
                    foreach (var id in tradeItem.additionalTradeItemIdentification)
                    {
                        var oid = oidService.GetOid(id.additionalTradeItemIdentificationTypeCode);
                        if (oid == null)
                        {
                            continue;
                        }
                        retVal.Identifiers.Add(new EntityIdentifier(new AssigningAuthority(oid.Mnemonic, oid.Name, oid.Oid), id.Value));
                    }
                }

                if (String.IsNullOrEmpty(tradeItem.itemTypeCode?.Value))
                {
                    throw new InvalidOperationException("Cannot auto-create material, type code must be specified");
                }
                else // lookup type code
                {
                    var concept = ApplicationContext.Current.GetService <IConceptRepositoryService>().FindConceptsByReferenceTerm(tradeItem.itemTypeCode.Value, tradeItem.itemTypeCode.codeListVersion).FirstOrDefault();
                    if (concept == null && tradeItem.itemTypeCode.codeListVersion == "OpenIZ-MaterialType")
                    {
                        concept = ApplicationContext.Current.GetService <IConceptRepositoryService>().GetConcept(tradeItem.itemTypeCode.Value);
                    }

                    // Type code not found
                    if (concept == null)
                    {
                        throw new InvalidOperationException($"Material type {tradeItem.itemTypeCode.Value} is not a valid concept");
                    }

                    // Get the material and set the type
                    retVal.TypeConceptKey = concept.Key;
                }

                // Find the type of material
                Material materialReference = null;
                if (tradeItem.tradeItemClassification != null)
                {
                    foreach (var id in tradeItem.tradeItemClassification.additionalTradeItemClassificationCode)
                    {
                        materialReference = this.m_materialRepository.FindMaterial(o => o.Identifiers.Any(i => i.Value == id.Value && i.Authority.DomainName == id.codeListVersion) && o.ClassConceptKey == EntityClassKeys.Material && o.StatusConceptKey != StatusKeys.Obsolete, 0, 1, out tr).SingleOrDefault();
                        if (materialReference != null)
                        {
                            break;
                        }
                    }
                }
                if (materialReference == null)
                {
                    materialReference = this.m_materialRepository.FindMaterial(o => o.TypeConceptKey == retVal.TypeConceptKey && o.ClassConceptKey == EntityClassKeys.Material && o.StatusConceptKey != StatusKeys.Obsolete, 0, 1, out tr).SingleOrDefault();
                }
                if (materialReference == null)
                {
                    throw new InvalidOperationException("Cannot find the base Material from trade item type code");
                }

                // Material relationship
                EntityRelationship materialRelationship = new EntityRelationship()
                {
                    RelationshipTypeKey        = EntityRelationshipTypeKeys.Instance,
                    Quantity                   = (int)(additionalData.tradeItemQuantity?.Value ?? 1),
                    SourceEntityKey            = materialReference.Key,
                    TargetEntityKey            = retVal.Key,
                    EffectiveVersionSequenceId = materialReference.VersionSequence
                };

                // TODO: Manufacturer won't be known

                // Insert the material && relationship
                ApplicationContext.Current.GetService <IBatchRepositoryService>().Insert(new Bundle()
                {
                    Item = new List <IdentifiedData>()
                    {
                        retVal,
                        materialRelationship
                    }
                });
            }
            else if (tradeItem.additionalTradeItemIdentification != null) // We may want to keep track of other identifiers this software knows as
            {
                bool shouldSave = false;
                foreach (var id in tradeItem.additionalTradeItemIdentification)
                {
                    var oid = oidService.GetOid(id.additionalTradeItemIdentificationTypeCode);
                    if (oid == null)
                    {
                        continue;
                    }
                    if (!retVal.Identifiers.Any(o => o.LoadProperty <AssigningAuthority>("Authority").DomainName == oid.Mnemonic))
                    {
                        retVal.Identifiers.Add(new EntityIdentifier(new AssigningAuthority(oid.Mnemonic, oid.Name, oid.Oid), id.Value));
                        shouldSave = true;
                    }
                }

                if (shouldSave)
                {
                    this.m_materialRepository.Save(retVal);
                }
            }

            return(retVal);
        }