Retrieving column mapping info in T4 - entity-framework-4.1

I'm working on a T4 file that generates .cs classes based on an entity model, and one of the things I'm trying to get to is the mapping info in the model. Specifically, for each field in the model I'm trying retrieve the database field name it is mapped to.
I've found that the mapping info is apparently stored in StorageMappingItemCollection, but am having an impossible time figuring out how to query it and retrieve the data I need. Has anyone worked with this class and can maybe provide guidance?
The code I have so far goes something like this (I've pasted everything up to the problematic line):
<#
System.Diagnostics.Debugger.Launch();
System.Diagnostics.Debugger.Break();
#>
<## template language="C#" debug="true" hostspecific="true"#>
<## include file="EF.Utility.CS.ttinclude"#>
<## output extension=".cs"#><#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
string inputFile = #"MyModel.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
StoreItemCollection storeItemCollection = null;
loader.TryCreateStoreItemCollection(inputFile, out storeItemCollection);
StorageMappingItemCollection storageMappingItemCollection = null;
loader.TryCreateStorageMappingItemCollection(
inputFile, ItemCollection, storeItemCollection, out storageMappingItemCollection);
var item = storageMappingItemCollection.First();
storageMappingItemCollection has methods like GetItem() and such, but I can't for the life of me get it to return data on fields that I know exist in the model.
Thx in advance!

Parsing the MSL isn't really that hard with Linq to XML
string mslManifestResourceName = GetMslName(ConfigurationManager.ConnectionStrings["Your Connection String"].ConnectionString);
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(mslManifestResourceName);
XmlReader xreader = new XmlTextReader(stream);
XDocument doc = XDocument.Load(xreader);
XNamespace xmlns = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
var items = from entitySetMap in doc.Descendants(xmlns + "EntitySetMapping")
let entityTypeMap = entitySetMap.Element(xmlns + "EntityTypeMapping")
let mappingFragment = entityTypeMap.Element(xmlns + "MappingFragment")
select new
{
EntitySet = entitySetMap.Attribute("Name").Value,
TypeName = entityTypeMap.Attribute("TypeName").Value,
TableName = mappingFragment.Attribute("StoreEntitySet").Value
};

It may be easier to parse the EDMX file as XML rather than using the StorageMappingItemCollection.

Related

BIML - 'AstTableNode' does not contain a definition for 'GetDropAndCreateDdl'

I am working on a BIML project to generate SSIS packages. I have a separate static class for utility methods.
I am attempting to call GetDropAndCreateDdl() to get the DDL from the souce to dynamically create a table in the destination. This should work in theory as it is referenced in multiple posts: here and here as samples.
When generating the BIML, running the sample code below, I receive an error: Error: 'AstTableNode' does not contain a definition for 'GetDropAndCreateDdl' and no accessible extension method 'GetDropAndCreateDdl' accepting a first argument of type 'AstTableNode' could be found
public static string GetDropAndCreateDDL(string connectionStringSource, string sourceTableName)
{
var sourceConnection = SchemaManager.CreateConnectionNode("Source", connectionStringSource);
var sourceImportResults = sourceConnection.ImportTableNodes(Nomenclature.Schema(sourceTableName),Nomenclature.Table(sourceTableName));
return sourceImportResults.TableNodes.ToList()[0].GetDropAndCreateDdl();
}
(Let's ignore the possibility of getting no table back or multiples for the sake of simplicity)
Looking at the varigence documentation, I don't see any reference to this method. This makes me think that there is a utility library that I am missing in my includes.
using Varigence.Biml.Extensions;
using Varigence.Biml.CoreLowerer.SchemaManagement;
What say you?
Joe
GetDropAndCreateDdl is an extension method in Varigence.Biml.Extensions.SchemaManagement.TableExtensions
ImportTableNodes returns an instance of
Varigence.Biml.CoreLowerer.SchemaManagement.ImportResults and the TableNodes is an IEnumerable of AstTableNodes
So, nothing weird there (like the table nodes in the import results being a different type)
I am not running into an issue if I have the code in-line with BimlExpress.
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<#
string connectionStringSource = #"Provider=SQLNCLI11;Data Source=localhost\dev2017;Integrated Security=SSPI;Initial Catalog=msdb";
var sourceConnection = SchemaManager.CreateConnectionNode("Source", connectionStringSource);
List<string> schemaList = new List<string>(){"dbo"};
var sourceImportResults = sourceConnection.ImportTableNodes("dbo", "");
WriteLine("<!-- {0} -->", sourceImportResults.TableNodes.Count());
//var sourceImportResults = sourceConnection.ImportTableNodes(schemaList,null);
var x = sourceImportResults.TableNodes.ToList()[0];
var ddl = x.GetDropAndCreateDdl();
WriteLine("<!-- {0} -->", sourceImportResults.TableNodes.FirstOrDefault().GetDropAndCreateDdl());
#>
</Biml>
The above code results in the following expanded Biml
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<!-- 221 -->
<!-- IF EXISTS (SELECT * from sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[autoadmin_backup_configuration_summary]') AND type IN (N'V'))
DROP VIEW [dbo].[autoadmin_backup_configuration_summary]
GO
CREATE VIEW [dbo].[autoadmin_backup_configuration_summary] AS
SELECT
ManagedBackupVersion,
IsAlwaysOn,
IsDropped,
IsEnabled,
RetentionPeriod,
EncryptionAlgorithm,
SchedulingOption,
DayOfWeek,
COUNT(*) AS DatabaseCount
FROM autoadmin_backup_configurations
GROUP BY
ManagedBackupVersion,
IsAlwaysOn,
IsDropped,
IsEnabled,
RetentionPeriod,
EncryptionAlgorithm,
SchedulingOption,
DayOfWeek
GO
-->
</Biml>

Json marshalling in dart

I have i small question about json serializing in dart. I am using "exportable" lib.
https://pub.dartlang.org/packages/exportable
Here a small code:
Condition t = new Condition();
Configurator configurator1 = new Exportable(Configurator);
configurator1.alias = conf_b_1;
configurator1.value = conf1;
Configurator configurator2 = new Exportable(Configurator);
configurator2.alias = conf_b_2;
configurator2.value = conf2;
t.configurators.add(configurator1);
ntp.condition = t;
print("________________toString_______________");
print(""+t.toString());
print("_______________________________________");
print("________________toJson_______________");
print(""+t.toJson());
print("_______________________________________");
and the result is:
________________toString_______________
{"ref":"4","logicalRefId":"41","value":"1","alias":false,"configurators":["{\"alias\":\"1\",\"value\":\"10\"}"]}
________________toJson_______________
{"ref":"4","logicalRefId":"41","value":"1","alias":false,"configurators":["{\"alias\":\"1\",\"value\":\"10\"}"]}
The configurator part is totally broken. Where am i doing it wrong ?
Thx in advance for reading me,
Nerio.

lightswitch html client failed to convert circular structure to json

Im trying to insert new data into the DB when a user scans a barcode into a field. When I hit save on the screen it says fail to convert circular structure to json.
var report = myapp.activeDataWorkspace.BlanccoData.BMCReports.addNew();
report.c_Date = Date.now();
report.IsScannedReport = true;
if (contentItem.screen.ScanSSN == true) {
report.SSN = contentItem.value;
}
var system = myapp.activeDataWorkspace.BlanccoData.BMCSystemInfo.addNew();
// system.Report = report;
system.Barcode = contentItem.screen.Barcode;
I think the commented line is throwing the exception but I need to reference it.
thanks
Have you considered that you may have a circular relationship in your database? That is reflected in your DataSource?

How to add multiple DataFlow tasks to a Foreach container

How to add multiple data flow tasks to a single foreach container using EzAPI. Basicly I need to do as following.
I am new to EzAPI. Can anyone give me a code sample for this kind of scenario. Thanks in advance.
Your question can really be distilled down to two questions: How do I create the various Containers and Tasks? How do I define precedence constraints between them?
As you can see in the code below, I create instances of the EzPackage, EzForEachLoop, EzExecSqlTask and EzDataFlowTask. EzAPI tasks and containers all accept a parent object in their constructor. This is how you specify what scope an object should exist at. Thus, the For Each Loop takes the base package as its argument but the Data Flow and Execute SQL Task use the For Each Loop so that they are created inside that container.
There are different mechanisms for defining the Precedence Constraint between objects and it's up to you which version you use: object.AttachTo vs package.PrecedenceConstraints.Add
public static void GimmieDaCodez()
{
EzPackage ezPackage = null;
EzForEachLoop ezLoop = null;
string packageName = #"so_22533130";
string outputFile = string.Format("{0}.dtsx",System.IO.Path.Combine(#"C:\Dropbox\Sandbox\UtumnoSandbox\EzAPIDemo\EzAPIDemo", packageName));
EzDataFlow df1 = null;
EzDataFlow df2 = null;
EzDataFlow df3 = null;
EzExecSqlTask t4 = null;
// Instantiate and configure our package
ezPackage = new EzPackage();
ezPackage.Name = packageName;
ezPackage.Description = "A package with a foreach enumerator and muliple data flows";
// Lazy initialization of FELC
ezLoop = new EzForEachLoop(ezPackage);
ezLoop.Name = "FELC Enumerate stuff";
ezLoop.Description = "EzAPI still does not allow configuration of FELC beyond file enumerator";
// Instantiate our tasks. Details left to the implementer
df1 = new EzDataFlow(ezLoop);
df1.Name = "DFT 1";
df2 = new EzDataFlow(ezLoop);
df2.Name = "DFT 2";
df3 = new EzDataFlow(ezLoop);
df3.Name = "DFT 3";
t4 = new EzExecSqlTask(ezLoop);
t4.Name = "SQL Do all the things";
df2.AttachTo(df1);
df3.AttachTo(df1);
t4.AttachTo(df2);
t4.AttachTo(df3);
ezPackage.SaveToFile(outputFile);
}
Using that code, I generate a package that looks like
References
My EzAPI posts
SSIS Team
EzAPI project subsite

LineageID is string or Integer

I'm trying to fetch lineageId of output columns in a SSIS Package. I'm traversing SSIS Package as XML Document in C# code.
No issue in traversing and fetching data from the nodes in the package, but facing issue when I'm trying to fetch LineageID.
I many forums and articles said that LineageId generated in SSIS Package is a Unique Integer value for that particular package, so I'm trying to convert LineageID to an integer value. But it seems to be a String value.
Kindly clarify my doubt. Is lineageid STRING OR INT?
If it is Int then please tell me how to find it.
foreach (var x in NodeCollection)
{
var outputCollection = x.Elements("outputColumn");
foreach (var output in outputCollection)
{
string Name = output.Attribute("name").Value;
long LineageId = Convert.ToInt64(output.Attribute("lineageId").Value);
}
}
By debugging with Breakpoint "output.Attribute("lineageId").Value" is returning following value
"Package\DFT\SRC.Outputs[OLE DB Source Output].Columns[TYPE]"
I have performed a very similar exercise and found that the lineage id values were definitely integer. This is an extract from my code:
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("DTS", "www.microsoft.com/SqlServer/Dts");
foreach (XmlNode childnode in doc.SelectNodes("//*[#lineageId != '' and #name != '']"))
{
XmlNode ExecutableNode = childnode.SelectSingleNode("ancestor::DTS:Executable[1]", nsmgr);
var taskName = ExecutableNode.SelectSingleNode("DTS:Property[#DTS:Name='ObjectName']", nsmgr).InnerText;
var targetColumnName = childnode.Attributes["name"].Value;
var lineageID = Convert.ToInt32(childnode.Attributes["lineageId"].Value);
We are using this to map column names to lineageid's so that we can interpret error messages thrown by our SSIS packages.
Hope this helps!