# 26 Haziran 2008 Perşembe
For VS2008: ActiveWriter Preview 4.1.rar (282.73 KB)
I'm not updating 2005 version anymore.

What's New:
  • Optionally generates classes implementing INotifyPropertyChanging.
  • Contrib-117: Database and designer column order is not in sync
Fixed:
  • Added "Nested" to Common.ARAttributes (Patch: Roberto Paterlini)
  • Swapped parameters in new ArgumentNullException (Patch: Roberto Paterlini)
  • Changed in-memory code compilation error reporting to give full details of the internal compile process. No more ExceptionCollection's.
  • Contrib-118: Activewriter errors in combination with VisualSVN (Patch: Visual SVN Team)
  • Changed the temporary file generation to use \obj folder rather than arbitrary locations on the system.


posted on 26 Haziran 2008 Perşembe 11:21:59 UTC  #   
# 18 Ağustos 2007 Cumartesi
This is mainly a service release, fixing some nasty bugs or "features".

AW now supports international versions of Visual Studio better. Preview 3 introduced hbm.xml generation but a bug prevented it to be usable without intevention. And drag-drop support for MySQL was broken if the user have a different version of Connector installed. All should work OK now.

Download here.

Preview 3.1 Release - 18/08/2007

What's New:
  • CONTRIB-31: "Lazy" One-to-One relation. (Thanks: Gabriel Schenker)

Fixes:

  • Server Explorer drag'n drop is now supported on international versions of VS. (Patch: Daniel Rothmaler)
  • Server Explorer support changed to VS Connection Service and its Connection Hierarchies, instead of the Server Explorer's UIHierarchies to prevent the flicker during the hierarchy traversing process. (Patch: Daniel Rothmaler)
  • Closing Contrib-25. ValidateNotSameAttribute Won't be supported ATM.
  • CONTRIB-33: When adding a table (SQL Server) to the designer which has a primary key of type uniqueidentifier ActiveWriter should use "Guid" instead of "Native" as generator (Thanks: Gabriel Schenker)
  • Assembly names in NHibernate configs are incorrectly stripped from the name. (Thanx: Fedde)
  • Removed dependency to MySQL.Data.dll to prevent runtime version conflicts. Moved to IDbConnection for all metadata retrieval jobs. (Thanks: Joao Paulo Marques and Shane)

posted on 18 Ağustos 2007 Cumartesi 12:39:10 UTC  #   
# 14 Haziran 2007 Perşembe
Preview 3 has this functionality, but there are a few things to mention.

ActiveWriter use ActiveRecord assembly to generate NHibernate config files. So you'll need Castle.ActiveRecord.dll, NHibernate.dll and all necessary dependincies to make it work.



  1. Set the target to NHibernate
    This way, AW will generate .hbm.xml files for each entity in your model.
  2. Set the Assembly Path to where Castle.ActiveRecord.dll, NHibernate.dll and all necessary dependincies reside.
    The design decision was that, I didn't want to package these assemblies with AW. Rather than that, I thought user will most probably have them so they can choose whatever version they want to generate the configuration. If you don't supply the path, AW (VS, actually) will look for them in GAc and then {Your VS Path}\Common7\IDE\Castle.ActiveRecord.dll, so if you have them in one of those places, it should be fine.

    One other quirk is, if you first try to generate with the wrong path, setti ng the correct one later won't work until you restart Visual Studio. This is the framework's limitation, once you try to load an assembly and get an error, the result will be cached for subsequent tries. So VS appdomain should be restarted to make it work. I'll have a possible soliton for this for a future version of ActiveWriter (will try to load in a dummy appdomain, then in the VS appdomain)

    You may use the fully qualified assembly names for Active Record Assembly Name and NHibernate Assembly Name to target a specific version in the GAC, if you have more than one in there.
  3. When you save the model, AW will generate configuration.
I'll prepare a better documentation in the wiki.

Have fun.

Update:

AW does not work with release version of Castle assemblies (RC2?) for NHibernate generation, it works with the trunk (or with recently compiled assemblies). You can use the latest bits from the build server: http://builds.castleproject.org/cruise/index.castle
posted on 14 Haziran 2007 Perşembe 11:46:32 UTC  #   

This was sitting on the trunk for a while because of a bug in NHibernate config generation. I believe it's fixed now, so let's see if it works :)

First of all, this release is trying to be compatible with Castle trunk, it may generate code usable by released Castle components but it follows recent changes (might miss a few days). You know, Castle will be 1.0 one day and ActiveWriter will be a release, not a preview, in that day.

And I'm trying create some documentation on using.castleproject.org (Castle's wiki) to make Hammett stop whining about the lack of documentation of contrib projects (kidding!). If you're using ActiveWriter and want to share your tips, tricks, workarounds or anything about it, it would be great if you contribute to the documentation.

The most important update is the direct NHibernate configuration support. Now you can instruct ActiveWriter to generate NHibernate configuration files (.hbm.xml) for each entity in your model. Generated classes won't have ActiveRecord attributes in this case. More on this in a later post (Update: here).



Another interesting change is the use of Castle.Components.Validator instead of the ActiveRecord validators. AR changed in the trunk to use it, so does ActiveWriter.



One more exiciting news is, you can drag tables of MySQL from Server Explorer onto the modelin surface (see Michael's patch below).

Full list of changes below. A big thanks to all who sent patches, ideas and bug reports.

New:
  • Now optionally generates NHibernate hbm.xml files.
  • Namespace in generated code is now customizable (Idea: Robert van Hoornaar)
  • Imports in generated code is now customizable (Idea: Robert van Hoornaar)
  • Model classes can override model level base class definition. (Patch: Robert van Hoornaar)
  • Model classes can override model level generics generation. (Idea: Robert van Hoornaar)
  • Contrib-26: Add support for AR Nested / NH Component mappings. Allow the ability to specify a column prefix for active record. (thx: Adam Tybor)
  • Optionally generates classes implementing INotifyPropertyChanged.
  • Support for drag-drop from Server Explorer for MySQL databases. Requires MySQL Connector/Net (5.1) (included). (Patch: Michael Morton)
  • Support for custom types through IUserType. See http://support.castleproject.org/browse/CONTRIB-28#action_11456 for usage. (Patch: Ricardo Stuven)
  • Ability to define a nested class with a different property name than the nested class (Idea: Craig Neuwirt)
Fixed:
  • Contrib-23: Produces CascadeEnum instead of ManyRelationCascadeEnum
  • Ability to generate virtual properties to support Lazy properly (thx: Ayende)
  • Make sure that Char and AnsiChar types are treated as a System.String types, instead of System.Char types (patch: Ayende)
  • HasAndbelongToMany does not take custom property names and not found behavior into account.
  • Can’t add a Many To Many relationship to 2 entities when the Class and Table names are different.
  • Column keys in many-to-one relations is not optional. (Patch: Robert van Hoornaar)
  • Partially fixing NHibernate code generation errors. Now works with a workaround.
  • Nullable types only when NotNull=false (Patch: Ricardo Stuven)
  • Changed to Castle.Components.Validator
And just one more thing. Someone asked me if ActiveWriter is a competitor for Linq to SQL. AW is just a servent of the heavyweight champion, NHibernate/AR combo. Linq to SQL is competing with NHibernate. I didn't have time to examine Linq to SQL designer, but it's built using DSL Tools just like ActiveWriter so some functionality should be alike. Other than that it's the framework, not the tools, important.
posted on 14 Haziran 2007 Perşembe 08:29:25 UTC  #   
# 25 Nisan 2007 Çarşamba
Both about MonoRail, actually.
Seeing your work used in screencasts is priceless.

posted on 25 Nisan 2007 Çarşamba 08:57:28 UTC  #   
# 18 Mart 2007 Pazar
Download here.

What's new:
  • Generics support (ActiveRecordBase<T> & ActiveRecordValidationBase<T>) (Generics is the default in the designer)
  • VB.NET seems OK (Not tested extensively).
  • Auto-sensing project type (C# or VB.NET) for code generation. You don't have to set that in the model anymore.
  • New ActiveWriter Class Details toolwindow. Can be used for rapidly adding class properties. (Idea: Ayende)
  • AR validators are supported for each property (not for field, key, composite key, timestamp or version) through a designer.
  • Ability to customize the base class. You can substitude your own base class from the editor or generate classes without a base class.
  • Ability to customize the source property name for associations. This is necessary for hierarchical objects, where they point to themselves, and using the class name resulted in un-compilable code in previous build. (Reported By: Ayende)
  • More domain consistency check through validations when opening / saving.
  • Applying pluralizing rules to the table name from the entity name if not specified. (Idea: Ayende)
  • Ability to select a property for optional DebuggerDisplay attribute.
  • Ability to decorate classes with GeneratedCodeAttribute.
  • No more setting Custom Tool property of an .actiw file to ActiveWriterCodeGenerator manually after creating the file. It's done automatically. (Thanks: Bogdan Pietroiu)
  • Key icon decorator on class shapes if a primary or composite key property exists (pure cosmetic).
  • Key icon decorator on class shapes if at least a property has validator(s) set (pure cosmetic).
  • Connector shapes changed to a more-UML-like notation.
  • Extended nullable support. You may choose between nullables through external Nullables library (1.1 style) or native nullables usage of 2.0 framework.
  • Some added properties to support changes (not all) in Castle trunk for ActiveRecordAttribute, PropertyAttribute etc.
  • Built with VS SDK v4. Includes new and improved version of DSL Tools redistributables.
What's crippled:
  • Using Output window less when doing drag-drop from Server Explorer to prevent a bug.
Known bugs / problems:
  • On international versions of VisualStudio, Drag'n drop support from Server Explorer generates entitites but not properties. You may create entities manually as a workaround.
  • Randomly, when you drag tables from Server Explorer, design surface gizes an error and cannot render any entities any more. You may save and re-open your .actiw file and it will catch up.
Screenshot below displays:
  • Validation support
  • Generic code generation
  • Nullables
  • Class details tool window
  • Visual hints on diagram elements
posted on 18 Mart 2007 Pazar 15:59:05 UTC  #   
# 12 Mart 2007 Pazartesi
I was using a private SVN for ActiveWriter and thanks to Hammet, the source is now available through Castle Contrib Repository.
Having source on an open repository is great. AW now has it's own Ohloh page :)
  • Codebase: 27,938 LOC (Most of them generated by DSL Tools, actually:)
  • Effort (est.): 7 Person Years
  • Project Cost: $362,806
I feel good! :)

posted on 12 Mart 2007 Pazartesi 10:11:10 UTC  #   
# 29 Ocak 2007 Pazartesi
I was trying to solve the Custom Tool property issue with .actiw files in ActiveWriter, as suggested by Bogdan Pietroiu months ago, and spent a clear hour trying to figure how to inject my own registry keys into WiX setup project of DSL Tools. I modified the .vstemplate for .actiw files to include the following:

...

<CustomParameters>

  <CustomParameter Name="$itemproperties$" Value="CustomTool" />

  <CustomParameter Name="$CustomTool$" Value="ActiveWriterCodeGenerator" />

</CustomParameters>

...


and thought that the file, when added to the project, will have Custom Tool property already set. I was appearently wrong (documentation says it should work).

Bogdan's suggestion was to have a key named after the file extension under Generators\{Language}, and I manually confirmed that it works great. So, how to automate the process of adding this reg key through the setup? WiX Toolkit documentation shows the way, so I copied Registry.wxs to have my own key registered.

<?xml version="1.0" encoding="utf-8"?>

<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>

  <Fragment Id="CustomToolFragment">

    <FeatureRef Id="DefaultFeature">

      <ComponentRef Id="_ActiveWriterCTReg" />

    </FeatureRef>

    <DirectoryRef Id="TARGETDIR">

      <Component Id="_ActiveWriterCTReg" Guid="{some GUID}">

        <Registry Root='HKLM' Key='Software\Microsoft\VisualStudio\8.0\Generators\{164b10b9-b200-11d0-8c61-00a0c91e29d5}\.actiw' Id='{some GUID}' Type='string' Value='ActiveWriterCodeGenerator' />

        <Registry Root='HKLM' Key='Software\Microsoft\VisualStudio\8.0\Generators\{fae04ec1-301f-11d3-bf4b-00c04f79efbc}\.actiw' Id='{some GUID}' Type='string' Value='ActiveWriterCodeGenerator' />

      </Component>

    </DirectoryRef>

  </Fragment>

</Wix>


<Registry> elements define the key to be added, as you may have guessed. Anyway, although I changed the build action on the .wxs and although it seems that Candle and Light picked up the file, the installer didn't add the registry key. So? Orca to the rescue. You should check Component and Registry tables in .msi file to check if your key slipped in, and Orca shows them quite detailed. In my case, though, it shows the absence of my additions.

Long story (not so) short, it seems that I should examine Registry.tt as the first step, but didn't. To include your ComponentRef in DefaultFeature, you should have your Fragment as FragmentRef in Main.wxs . So, you should add each of your custom fragment in the list defined in customFragmentIds in InstallerDefinitions.dslsetup as shown below:

<installerDefinition xmlns="http://schemas.microsoft.com/VisualStudio/2005/DslTools/InstallerDefinitionModel"

  ...

  customFragmentIds="CustomToolFragment">

I hope this info helps someone.

posted on 29 Ocak 2007 Pazartesi 21:13:31 UTC  #   
# 11 Ekim 2006 Çarşamba
I can't dechiper legal documents even in Turkish, how can I decide if I'm allowed to release the source code or not by looking at the VS DSK license? If Microsoft has a department or something to ask "would you get angry if I release this?", I want to know.

Anyway, you can download the source of ActiveWriter Preview here. I have removed some .tt files copyrighted by Microsoft, but instructions are available in the download to add them from an empty DSL Tools project. Lack of .tt files will prevent any "just extract and open" scenario, sorry about that.

Back to the license adventure. I have asked in DSL Tools forum if it's possible to release the source, and directed to the SDK license. Then I found a post on Interop blog, saying that "It is possible to release extensions to Visual Studio under open source licenses" with an IANAL notice. I have convinced that I can, until I notice copyright notes on all over the .tt files, which are very much the core of the code generation on DSL Tools part. So I followed the next best approach, removed copyrighted stuff.

Having copyright notices in .tt files, for Microsoft, is a bit silly, by the way. They don't include notices in AssemblyInfo or config files (or any other template generated solution files), what's different with .tt's?

Update:

Gareth Jones from DSL Tools team replied, saying that .tt files are considered to be samples and developers may customize them with whatever license statements they have. This is extremely good. I'll re-release the source with all the .tt files included.

And for those who don't know what a .tt file is for; they are input files for the text templating engine of DSL Tools. They have ASP.NET like <# #> syntax to generate output as VS solution files. Very handy, but I prefered a more classic approach in ActiveWriter. CodeGenerationHelper is much nicer in plain C# than .tt syntax.

ActiveWriterReport.tt file:

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" debug="true"#>
<#@ output extension=".%EXT%" #>
<#@ ActiveWriter processor="ActiveWriterDirectiveProcessor" requires="fileName='%MODELFILE%'" #>
<#@ import namespace="Altinoren.ActiveWriter.CodeGeneration" #>
<#
    CodeGenerationHelper helper = new CodeGenerationHelper(this.Model, "%NAMESPACE%");
    this.Write(helper.Generate());
#>

and the usage:

protected override byte[] GenerateCode(string inputFileName, string inputFileContent)

{

    ResourceManager manager =

        new ResourceManager("Altinoren.ActiveWriter.VSPackage",

                            typeof (ActiveWriterTemplatedCodeGenerator).Assembly);

    FileInfo fi = new FileInfo(inputFileName);

    inputFileContent =

        manager.GetObject("ActiveWriterReport").ToString().Replace("%MODELFILE%", fi.Name).Replace(

            "%NAMESPACE%", FileNameSpace).Replace("%EXT%", "cs"); // TODO: Get file extension from the project model

 

    byte[] data = base.GenerateCode(inputFileName, inputFileContent);

    return data;

}


posted on 11 Ekim 2006 Çarşamba 09:59:00 UTC  #   
# 30 Eylül 2006 Cumartesi

Help and download available here.

If you missed the announcement, it is a visual designer, an addin for Visual Studio 2005, to design a domain model and to generate code decorated with ActiveRecord attributes.

Please send bugs, suggestions and feature request through the Navigation pane of the site.

Thanks To

ActiveRecord team for the great and well supported library, NHibernate and Hibernate community for making this chain-reaction possible, Microsoft DSL Tools team for making DSL modelling this easy, everyone at DSL Tools forum, and my wife Damla for her patience.

Pluralization code is simplified version of Damian Conway's algorithm in paper An Algorithmic Approach to English Pluralization
Server Explorer integration greatly inspired from Ted Glaza's post here.
posted on 30 Eylül 2006 Cumartesi 18:12:03 UTC  #   
# 15 Eylül 2006 Cuma

Head to the VSIP member site to download. I'm %46 done right now.

Since DSL Tools v1 is bundled with this final release, and since I'll finally be able to include redistributables with ActiveWriter installer, I'm twice excited right now :)

My plan is:

    Compile ActiveWriter against DSL Tools v1
    Fix things broken by the v1
    Add one2one support (Just manual modelling. No heuristics for drag-drop. Will complete that later)
    Test & release.

 And about the current state of the project:

    Handles many-to-one, both in manual design and drag-drop.
    Handles many-to-many, both in manual design and drag-drop.
    Primary keys, properties, fields.
    Composite keys: Writes the attribute as well as a separate composite key class :) Yup.
    Some more model validators (If PrimaryKeyType.Sequence, then sequence name should be defined etc.)
    Versions and Timestamps.
posted on 15 Eylül 2006 Cuma 12:31:35 UTC  #   
# 28 Ağustos 2006 Pazartesi
I use CodeDom to generate ActiveRecord classes in ActiveWriter. Quite fancy, but gets complicated easily. To generate something like this:

        public override bool Equals(object obj)

        {

            if (obj == this) return true;

            if (obj == null || obj.GetType() != this.GetType()) return false;

            MyCompositeKey test = (MyCompositeKey)obj;

            return (_keyA == test.KeyA || (_keyA != null && _keyA.Equals(test.KeyA))) &&

              (_keyB == test.KeyB || (_keyB != null && _keyB.Equals(test.KeyB)));

        }


you code this:

        private CodeTypeMember GetCompositeClassEqualsMethod(string className,  List<CodeMemberField> fields)

        {

            CodeMemberMethod equals = new CodeMemberMethod();

            equals.Attributes = MemberAttributes.Public | MemberAttributes.Override;

            equals.ReturnType = new CodeTypeReference(typeof(Boolean));

            equals.Name = "Equals";

 

            CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(typeof(Object), "obj");

            equals.Parameters.Add(param);

 

            equals.Statements.Add(new CodeConditionStatement(

                                      new CodeBinaryOperatorExpression(

                                          new CodeFieldReferenceExpression(null, "obj"),

                                          CodeBinaryOperatorType.ValueEquality, new CodeThisReferenceExpression()

                                          ), new CodeMethodReturnStatement(new CodePrimitiveExpression(true))

                                      )

                );

 

            equals.Statements.Add(new CodeConditionStatement

                                      (

                                      new CodeBinaryOperatorExpression

                                          (

                                          new CodeBinaryOperatorExpression(

                                              new CodeFieldReferenceExpression(null, "obj"),

                                              CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(null)),

                                          CodeBinaryOperatorType.BooleanOr,

                                          new CodeBinaryOperatorExpression(

                                              new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(null, "obj"), "GetType"),

                                              CodeBinaryOperatorType.IdentityInequality,

                                              new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "GetType"))

                                          )

                                      , new CodeMethodReturnStatement(new CodePrimitiveExpression(false))

                                      )

                );

 

            equals.Statements.Add(

                new CodeVariableDeclarationStatement(new CodeTypeReference(className), "test",

                                                    new CodeCastExpression(new CodeTypeReference(className),

                                                                            new CodeFieldReferenceExpression(null, "obj"))));

 

            List<CodeExpression> expressions = new List<CodeExpression>();

            foreach (CodeMemberField field in fields)

            {

                expressions.Add(

                    new CodeBinaryOperatorExpression(

                        //_keyA == test.KeyA

                        new CodeBinaryOperatorExpression(

                            new CodeFieldReferenceExpression(null, field.Name),

                            CodeBinaryOperatorType.ValueEquality,

                            new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(null, "test"), field.Name)),

                        CodeBinaryOperatorType.BooleanOr, // ||

                        new CodeBinaryOperatorExpression(

                            //_keyA != null

                            new CodeBinaryOperatorExpression(

                                new CodeFieldReferenceExpression(null, field.Name),

                                CodeBinaryOperatorType.IdentityInequality,

                                new CodePrimitiveExpression(null)

                                ),

                            CodeBinaryOperatorType.BooleanAnd, // &&

                            // _keyA.Equals( test.KeyA )  

                            new CodeMethodInvokeExpression(

                                new CodeFieldReferenceExpression(null, field.Name), "Equals",

                                new CodeFieldReferenceExpression(

                                    new CodeFieldReferenceExpression(null, "test"), field.Name))

                            )

                        )

                    );

            }

 

            CodeExpression expression = null;

            if (expressions.Count > 2)

                expression =

                    new CodeBinaryOperatorExpression(expressions[0], CodeBinaryOperatorType.BooleanAnd, GetBooleanAnd(expressions, 1));

            else

                expression = new CodeBinaryOperatorExpression(expressions[0], CodeBinaryOperatorType.BooleanAnd, expressions[1]);

 

 

            equals.Statements.Add(new CodeMethodReturnStatement(expression));

 

            return equals;

        }


Strangely, there's no CodeBinaryOperatorType.ValueInequality operator defined. (a==b)==false will do the trick, but how about not having an XOR? I find CodeDom's lack of completeness... disturbing.

posted on 28 Ağustos 2006 Pazartesi 21:46:29 UTC  #   
# 19 Ağustos 2006 Cumartesi

ActiveWriter is a DLinq designer like addin for Visual Studio 2005 to design a domain model and to generate code decorated with ActiveRecord attributes.

 

 

It supports / will support:

  • Modeling
    Classes (Almost done)
    Class properties (Almost done)
    Setting a property as primary keys (Done)
    Setting more than one property as composite key (TBI)
    Many to One (Done), One to One, Many to Many relations (TBI)
    Nested classes (TBI)
    ... and more (I'm targeting to support the whole ActiveRecord model)
  • Model validation
    Current build validates most common things like classes without names, spaces in class names etc.
  • Drag and drop of table(s) from Server Explorer
    Can place tables, populate properties. I'm working on relations right now.
  • Automatic generation of source code of the model on save.
    Not implemented yet, but I know how to do it. Right now, it goes through .tt file.
  • Multiple database types as drag/drop source.
    Working on SQL Server right now. Oracle and others will follow.

I use the current CTP of DSL Tools to build the base. There are no downloadable bits right now, since I have to get a VSIP licence to make it run without the SDK.

I don't know to what extent I can open the source. I'll sure make the source downloadable but since part of the code is generated by DSL Tools and there's this VSIP licence, I may not be able to licence it under BSD or something. I'll look for it.

Anyway, I believe it will be a nice addin to have for people working with ActiveRecord/NHibernate. I'm doing my best to release a preview in one or two months.

Comments and suggestions are welcome.


posted on 19 Ağustos 2006 Cumartesi 11:02:33 UTC  #   

It's a black hole since its so massive that even a tiny piece of information on it's usage cannot escape out. Start writing an addin for Visual Studio and you'll find lots of information on the net. Enter into realms of Server Explorer, and you'll feel the massive darkness.

I'm coding and addin for Visual Studio 2005 using DSL Tools. Apart from the relatively steep learning curve of DSL Tools, it was going fine. By the very nature of the project, I started thinking on adding drag and drop of tables from Server Explorer. There are some DSRef and UIHierarchy usage examples on the net, so I thought it will be a piece of cake, until I find out there's no simple way of getting the underlying object model for data connections in Server Explorer, thanks to Microsoft's ability to mark everything Server Explorer as Private or Internal.

Long story short, after long nights and hours of Reflector and thousands of evasive maneuvers against the missile fired by my wife, here's how you get the DbConnection instance of Server Explorer holding the tables dropped on your design surface:

        private static DataConnection GetDataConnection(DTE dte, string itemName)

        {

            IntPtr ptr = IntPtr.Zero;

            try

            {

                if (((IServiceProvider)dte).QueryService(ref ServerExplorer, ref IUnknown, out ptr) >= 0)

                {

                    object o = Marshal.GetObjectForIUnknown(ptr);

                    if (o != null)

                    {

                        object dataConnectionsNode = GetField(o, "lastBrowseObjectNodeSite");

                        if (dataConnectionsNode != null)

                        {

                            INodeSite nodeSite =

                                (INodeSite)dataConnectionsNode;

 

                            INodeSite[] nodes = nodeSite.FindChildrenByLabel(itemName);

                            if (nodes != null && nodes.Length > 0)

                            {

                                object expNode = GetField(nodes[0], "expNode");

                                if (expNode != null)

                                {

                                    object nestedHierarchy = GetField(expNode, "nestedHierarchy");

                                    if (nestedHierarchy != null)

                                    {

                                        DataConnection connection =

                                            GetProperty(nestedHierarchy, "DataConnection") as DataConnection;

                                        if (connection != null)

                                        {

                                            return connection;

                                        }

                                    }

                                }

                            }

                        }

                    }

                }

            }

            finally

            {

                Marshal.Release(ptr);

            }

 

            return null;

        }

        private static object GetField(object o, string fieldName)

        {

            if (o != null && !String.IsNullOrEmpty(fieldName))

                return o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(o);

 

            return null;

        }

 

        private static object GetProperty(object o, string fieldName)

        {

            if (o != null && !String.IsNullOrEmpty(fieldName))

                return o.GetType().GetProperty(fieldName).GetValue(o, null);

 

            return null;

        }

Once you get DataConnection, try ConnectionSupport.ProviderObject property to get the actual DbConnection. Happily, VS loaded addins cannot load new assemblies into AppDomain but at least allowed reflection.

posted on 19 Ağustos 2006 Cumartesi 09:49:55 UTC  #   

...but Foreign Key support is just useless, especially for SqlConnection. Just look at the table signature:

ColumnName DataType Description

constraint_catalog

String

Catalog the constraint belongs to.

constraint_schema

String

Schema that contains the constraint.

constraint_name

String

Name.

table_catalog

String

Table Name constraint is part of.

table_schema

String

Schema that that contains the table.

table_name

String

Table Name

constraint_type

String

Type of constraint. Only "FOREIGN KEY" is allowed.

is_deferrable

String

Specifies whether the constraint is deferrable. Returns NO.

initially_deferred

String

Specifies whether the constraint is initially deferrable. Returns NO.

Quite disappointing, since there's no sign of columns involved. And there's no other GetSchema() way to get them. OracleConnection, on the other hand has a collection called ForeignKeyColumns, which returns columns included for a given FK relationship in a given table. Once you have the FK relation, you should query both sides to get the full column list, though, but better than nothing.

So, with SqlConnection, I use sp_fkeys in ActiveWriter. I wish I could just use GetSchema(), to keep things simple. Sad.

posted on 19 Ağustos 2006 Cumartesi 08:59:42 UTC  #