Мы используем последнюю версию IdeaBlade 2012 в нашем проекте, в нашей вспомогательной функции, она показывает «имя таблицы». «Имя поля», и пользователь может добавлять комментарии и сохранять их в одной таблице. В EF он может получить dbContext.MetadataWorkspace для получения метаданных в edmx, но как мы можем получить его в EntityManager?Как получить имя таблицы/поля в IdeaBlade 2012?
ответ
Как упоминал Ким Джонсон в своем комментарии, настройка генерации кода может работать очень хорошо для этого. Мы сделали это в нашем приложении, чтобы добавить дополнительные комментарии к каждому объекту и полю, содержащему имя таблицы/столбца. Это помогает разработчикам C#, поскольку мы иногда переименовываем объекты/свойства и пытаемся отобразить их обратно на бэкэнд, может быть сложно.
Однако в последнее время нам нужны еще данные из модели EF и приступили к анализу XML EDMX напрямую. Это дает нам всю необходимую информацию. Он даже коррелировал данные EDMX с метаданными DevForce и даже данными отражения.
Вот полный код для любого заинтересованного. Это много кода, но, надеюсь, легко следовать. И это, вероятно, делает больше, чем нужно большинству людей.
/// <summary>
/// Helper class for parsing the EDMX model, looking up DevForce metadata as well as C# reflection data and then combining it all
/// into organized data structures.
/// </summary>
public static class ModelDataExtractor
{
/// <summary>
/// Information about a property/column from an EDMX.
/// </summary>
public class EdmxColumnInfo
{
public string TableName { get; set; }
public string ColumnName { get; set; }
public string SqlType { get; set; }
public bool? Nullable { get; set; }
public int? MaxLength { get; set; }
public bool? FixedLength { get; set; }
public bool? IsUnicode { get; set; }
}
/// <summary>
/// Collection of information about a property.
/// </summary>
public class ExtraPropertyInfo
{
public PropertyInfo CSharpProperty { get; set; }
public EntityProperty DevForceProperty { get; set; }
public EdmxColumnInfo EdmxData { get; set; }
public string TypeHierarchy { get; set; }
}
/// <summary>
/// Extracts the data from the EDMX's embeded in the Business assembly.
/// </summary>
public static List<ExtraPropertyInfo> ExtractData()
{
var assembly = typeof(MyFavoriteEntity).Assembly;
var all = from name in assembly.GetManifestResourceNames()
where name.EndsWith(".csdl") || name.EndsWith(".msl") || name.EndsWith(".ssdl")
let xml = XElement.Load(assembly.GetManifestResourceStream(name))
select new EdmxFragment(name.Replace(".csdl", "").Replace(".msl", "").Replace(".ssdl", ""), xml);
return ExtractData(all.ToList());
}
/// <summary>
/// Extracts the data from the EDMX's in the given directory
/// </summary>
public static List<ExtraPropertyInfo> ExtractData(string dataModelPath)
{
return ExtractData(
Directory.GetFiles(dataModelPath, "*.edmx")
.Select(fileName => new EdmxFragment(fileName, XElement.Load(fileName)))
.ToList());
}
/// <summary>
/// Provides the ability for multiple XElements to be treated as multiple fragments of the same logical EDMX.
/// </summary>
private class EdmxFragment
{
public EdmxFragment(string edmxName, XElement documentRoot)
{
EdmxName = edmxName;
DocumentRoot = documentRoot;
}
public string EdmxName { get; private set; }
public XElement DocumentRoot { get; private set; }
}
private static List<ExtraPropertyInfo> ExtractData(IList<EdmxFragment> edmxFragments)
{
//If we aren't given any fragments...well, nothing to do really
if (edmxFragments.Count == 0)
{
return new List<ExtraPropertyInfo>();
}
//Derive the correct namespaces to use
var ns = EdmxNamespaceHelper.DeriveNamespaces(edmxFragments[0].DocumentRoot);
//First extract data out of the EDMXs 'sections'
//Parse the SSDL data for each XML document
var storageTypes = from fragment in edmxFragments
from entityType in fragment.DocumentRoot.Descendants(XName.Get("EntityType", ns.Ssdl))
from prop in entityType.Elements(XName.Get("Property", ns.Ssdl))
select new
{
TableName = entityType.GetString("Name"),
ColumnName = prop.GetString("Name"),
SqlType = prop.GetString("Type"),
Nullable = prop.GetBool("Nullable"),
MaxLength = prop.GetInt("MaxLength"),
fragment.EdmxName
};
//Parse the CSDL data for each XML document
var conceptualTypes = from fragment in edmxFragments
from entityType in fragment.DocumentRoot.Descendants(XName.Get("EntityType", ns.Csdl))
from prop in entityType.Elements(XName.Get("Property", ns.Csdl))
select new
{
TypeName = entityType.GetString("Name"),
PropertyName = prop.GetString("Name"),
FixedLength = prop.GetBool("FixedLength"),
IsUnicode = prop.GetBool("Unicode"),
fragment.EdmxName
};
//Parse the MSDL data for each XML document
var mappings = from fragment in edmxFragments
from setMap in fragment.DocumentRoot.Descendants(XName.Get("EntitySetMapping", ns.Msdl))
let typeMap = setMap.Elements(XName.Get("EntityTypeMapping", ns.Msdl)).Single()
let mapFragment = typeMap.Elements(XName.Get("MappingFragment", ns.Msdl)).Single()
from prop in mapFragment.Elements(XName.Get("ScalarProperty", ns.Msdl))
let fullTypeName = typeMap.GetString("TypeName")
let typeName = fullTypeName.Substring(fullTypeName.LastIndexOf(".", StringComparison.Ordinal) + 1)
select new
{
TypeName = typeName,
TableName = mapFragment.GetString("StoreEntitySet"),
PropertyName = prop.GetString("Name"),
ColumnName = prop.GetString("ColumnName"),
fragment.EdmxName
};
//Using the mapping info to join the Conceptual and Storage info
var tempCombined = from storageInfo in storageTypes
join mapping in mappings
on new { storageInfo.ColumnName, storageInfo.TableName, storageInfo.EdmxName }
equals new { mapping.ColumnName, mapping.TableName, mapping.EdmxName }
join conceptualInfo in conceptualTypes
on new { mapping.PropertyName, mapping.TypeName, mapping.EdmxName } equals
new { conceptualInfo.PropertyName, conceptualInfo.TypeName, conceptualInfo.EdmxName }
select new
{
storageInfo,
mapping,
conceptualInfo
};
//Flatten the information from the Conceptual and Storage info
var edmxInfo = from c in tempCombined
select new
{
c.mapping.TypeName,
c.mapping.PropertyName,
ColumnInfo = new EdmxColumnInfo
{
TableName = c.storageInfo.TableName,
ColumnName = c.storageInfo.ColumnName,
SqlType = c.storageInfo.SqlType,
Nullable = c.storageInfo.Nullable,
MaxLength = c.storageInfo.MaxLength,
IsUnicode = c.conceptualInfo.IsUnicode,
FixedLength = c.conceptualInfo.FixedLength,
}
};
//Build a dictionary for easy retrieval
var fullEdmxData = edmxInfo.ToDictionary(d => d.TypeName + "." + d.PropertyName,
d => d.ColumnInfo);
//Use Reflection and DevForce metadata to inspect the C# code
var results =
//Go through all the Types in assembly that 'my favorite entity' is in
from cSharpType in typeof(MyFavorateEntity).Assembly.GetTypes()
//Ignore abstract classes (the virtual entities probably)
where !cSharpType.IsAbstract
//Only process types that are Entities
where cSharpType.IsSubclassOf(typeof(Entity))
//Build the class hierarchy as a string
let hierarchy = GetAncestors(cSharpType).GetDelimitedString(" > ", t => t.Name)
//Let all the C# properties (except the XYZProperty ones)
let codeProperties = cSharpType.GetProperties()
//Get the metadata from DevForce
let modelMetadata = EntityMetadataStore.Instance.GetEntityMetadata(cSharpType)
//Combine the C# data, the DevForce data and the EDMX data
let combined = from codeProperty in codeProperties
join modelProperty in modelMetadata.EntityProperties
on codeProperty.Name equals modelProperty.Name into
matchedModelProperties
let singleMatchedModelProperty = matchedModelProperties.SingleOrDefault()
let typePropString = cSharpType.Name + "." + codeProperty.Name
let edmxData =
fullEdmxData.ContainsKey(typePropString)
? fullEdmxData[typePropString]
: null
select new ExtraPropertyInfo
{
TypeHierarchy = hierarchy,
CSharpProperty = codeProperty,
DevForceProperty = singleMatchedModelProperty,
EdmxData = edmxData
}
from c in combined
select c;
return results.ToList();
}
private static IEnumerable<Type> GetAncestors(Type t)
{
var parent = t.BaseType;
while (parent != typeof(Entity) && parent != null)
{
yield return parent;
parent = parent.BaseType;
}
}
}
/// <summary>
/// Helper class to dynamically determine the EDMX version (and therefore namespace names) of a particular EDMX file (or fragment)
/// </summary>
internal class EdmxNamespaceHelper
{
public string Edmx { get; private set; }
public string Csdl { get; private set; }
public string Ssdl { get; private set; }
public string Msdl { get; private set; }
/// <summary>
/// Version 2 namespaces
/// </summary>
private static readonly EdmxNamespaceHelper V2 = new EdmxNamespaceHelper
{
Edmx = "http://schemas.microsoft.com/ado/2008/10/edmx",
Csdl = "http://schemas.microsoft.com/ado/2008/09/edm",
Ssdl = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl",
Msdl = "http://schemas.microsoft.com/ado/2008/09/mapping/cs"
};
/// <summary>
/// Version 3 namespaces
/// </summary>
private static readonly EdmxNamespaceHelper V3 = new EdmxNamespaceHelper
{
Edmx = "http://schemas.microsoft.com/ado/2009/11/edmx",
Csdl = "http://schemas.microsoft.com/ado/2009/11/edm",
Ssdl = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl",
Msdl = "http://schemas.microsoft.com/ado/2009/11/mapping/cs"
};
/// <summary>
/// Sees is this instance's namespaces seem to be valid for the given <see cref="XElement"/> root.
/// </summary>
private bool IsValid(XElement xmlRoot)
{
try
{
//See if the top element is the Runtime element (for .edmx files)
return xmlRoot.Element(XName.Get("Runtime", Edmx)) != null ||
//or if the root has a namespace of one of the individual sections (for fragments)
xmlRoot.Name.NamespaceName.In(Edmx, Csdl, Ssdl, Msdl);
}
catch
{
return false;
}
}
/// <summary>
/// Determines the correct <see cref="EdmxNamespaceHelper"/> for the given <see cref="XElement"/> root.
/// </summary>
public static EdmxNamespaceHelper DeriveNamespaces(XElement xmlRoot)
{
//Try V2 and V3. If none of them seem to match, just error out.
if (V2.IsValid(xmlRoot))
return V2;
if (V3.IsValid(xmlRoot))
return V3;
throw new InvalidOperationException("Could not determine EDMX type of given XML Document");
}
}
- 1. Ideablade Update
- 2. AX 2012 - Получить имя экземпляра не имя сервера в X ++
- 3. Microsoft SQL Profiler с IdeaBlade
- 4. EFProf (Entity Framework Profiler) с IdeaBlade
- 5. Как получить имя компьютера?
- 6. Контейнер для коктейлей Ideablade для проектов WCF
- 7. EntityModel с Ideablade давая проблемы на сервере
- 8. DevForce Ideablade Фильтр по динамической колонке
- 9. Как получить только имя домена в SQLite?
- 10. Как получить имя вызывающей формы в поле Insert() таблицы в AX 2012?
- 11. Задайте адрес сервера динамически в ideablade во второй раз?
- 12. Persist Имя пользователя visual studio 2012
- 13. linux shell получить имя файла
- 14. Как получить имя фрейма
- 15. Как получить имя формы
- 16. Как получить имя файла?
- 17. Как получить имя указателя
- 18. Как получить имя пользователя?
- 19. Как получить имя CardHolder
- 20. Как получить имя семафора
- 21. Как получить имя метода?
- 22. Как получить имя функции?
- 23. Как получить имя раскадровки?
- 24. Как получить имя файла?
- 25. Как получить имя файла
- 26. Как получить имя константы?
- 27. Как получить имя UIColor?
- 28. Как получить имя компонента?
- 29. Как получить имя объекта?
- 30. Как получить имя ресурса?
EntityManager не имеет доступа к именам таблиц и столбцов базы данных, поскольку он работает только с «концептуальным» уровнем модели. Однако у вас есть несколько вариантов, если вы хотите сделать это в DevForce. Один из них заключается в настройке шаблона генерации кода для включения этой информации в вашу сгенерированную модель в качестве, возможно, настраиваемых свойств или атрибутов. Другой - построить DbContext самостоятельно в DF-серверном коде, таком как перехватчик сохранения. –
Спасибо! Вариант № 1 работает. –
Есть некоторая информация о Центре ресурсов DevForce, чтобы начать работу - http://drc.ideablade.com/devforce-2012/bin/view/Documentation/custom-code-generation-template. Если вам нужно больше, вы можете открыть запрос поддержки через веб-сайт IdeaBlade. –