Id generation problems

Jan 29, 2014 at 8:34 AM
Edited Feb 4, 2014 at 9:03 AM
  1. I would like to use friendly id instead of guid, so instead of bsdb generating a guid i would like to pass a function that takes care of the generation.
    In my particular case I am using code from here
    Also for the future the int alternative could be considered: autoint
I thing this part with friendly id's is important because in lots of scenarios the id is used in url (eg stackoverflow, codeplex, etc)

2 . Having a base class with an id and and identifier attribute doesn't work
 public interface IBase{
 [Identifier("http://www.example.com/")]
  string Id { get; }

public interface Concrete: IBase
Outputs ids like:
http://www.brightstardb.com/.well-known/genid/c74f5f37-ef4e-421b-b830-de840d435e58

3 . Adding a prefix like this: [Identifier("domain:")] , doesn't work. It expects to have something after prefix. In my case I want to have just a prefix followed by id like:
http://www.brightstardb.com/c74f5f37-ef4e-421b-b830-de840d435e58
So i have to do:
[assembly: NamespaceDeclaration("domain", "http://www.example.com")]
[Identifier("domain:/")]
So I'm moving that "/" from namespace to identifier.
Feb 5, 2014 at 8:58 AM
Related to point 2:
i've changed to add identifiers for inherited interfaces, seems to work for now:

ReflectionMappingProvider.cs
private static void AddMappingsForType(EntityMappingStore mappingStore, AssemblyMappingInfo assemblyMappingInfo, Type mappedType)
        {
        ......................................................................
                    if (identifierAttr != null && !String.IsNullOrEmpty(identifierAttr.BaseAddress))
                    {
                        var identifierPrefix = assemblyMappingInfo.ResolveIdentifier(identifierAttr.BaseAddress);
                        mappingStore.SetIdentifierPrefix(mappedType, identifierPrefix);
                        var propertyHint = new PropertyHint(PropertyMappingType.Id);
                        mappingStore.SetPropertyHint(identityProperty, propertyHint);
                        var derivedInterfaces = (from lAssembly in AppDomain.CurrentDomain.GetAssemblies()
                                         from lType in lAssembly.GetTypes()
                                         where mappedType.IsAssignableFrom(lType) 
                                         && mappedType.IsInterface
                                         select lType).ToArray();
                        foreach (var derivedInterface in derivedInterfaces)
                        {
                            if (derivedInterface.GetCustomAttributes(typeof (EntityAttribute), false).Length == 0)
                                continue;
                            mappingStore.SetIdentifierPrefix(derivedInterface, identifierPrefix);
                            mappingStore.SetPropertyHint(identityProperty, propertyHint);
                        }
                    }
                    else
                    {
                        mappingStore.SetPropertyHint(identityProperty, new PropertyHint(PropertyMappingType.Address));
                    }
                }
Coordinator
Feb 5, 2014 at 5:44 PM
Have you checked that this change would allow you to override the prefix in a derived interface (and keep the override in any interfaces dervied from that one). I'm concerned that you might be dependent on the order of evaluation of interfaces with this code.
Feb 6, 2014 at 7:11 AM
You are probably right, but this is a quick fix that allows me to solve this problem in a simple inheritance scenario. Reading "AppDomain.CurrentDomain.GetAssemblies" for each type seems like a bad idea anyway. I think the way to go here is to have a unit test that simulates scenarios 1,2,3. About the actual solution I'm not that familiar with the EF implementation so it's better for someone who knows it to make the changes.

As a more general perspective, I'm trying to use the api in a real world app, so i'm getting into various bumps. I had an api written by me but that was in limited time and had far less functionality/tests than bsdb ef implementation, plus no benefits from open source community, so now i'm try to migrate and see if I can use the api. But I need inheritance, I need to map EF POCO to DTO and back and write custom queries that work with graphs. If a problem is a showstopper like the inheritance one, or the context.EntitySet<T> i try to do quickfixes/report here on forum.
Feb 17, 2014 at 9:00 AM
Another minor issue:
[Entity]
public interface ITweet {
  ...
  ICollection<IHashTag> HashTags { get; set; }
  ...
}

[Entity]
public interface IHashTag {
  ...
  [InverseProperty("HashTags")]
  ICollection<ITweet> Tweets { get; set; }
  ...
}
In db it will gen triples like:
:id :HashTags :id
instead of singular:
:id :HashTag :id
Coordinator
Feb 18, 2014 at 1:33 PM
That should be simple to workaround, just add a [PropertyType("HashTag")] attribute to your HashTags property in ITweet.
Apr 1, 2014 at 12:30 PM
In v1.6 EntitymappingStore the method that returns prefix also needs to get from base interfaces:
 public string GetIdentifierPrefix(Type mappedType)
        {
            string prefix;
            Type interfaceType;
            if (_identifierPrefixes.TryGetValue(mappedType, out prefix))
            {
                return prefix;
            }
            if (_interfaceMappings.TryGetValue(mappedType, out interfaceType) &&
                _identifierPrefixes.TryGetValue(interfaceType, out prefix))
            {
                return prefix;
            }

            foreach (var @interface in mappedType.GetInterfaces())
            {
                if (_identifierPrefixes.TryGetValue(@interface, out prefix))
                {
                    return prefix;
                }
            }
            return null;
        }
Coordinator
Apr 1, 2014 at 3:34 PM
Fixed in the develop branch. Thanks.