I'm new to SQL Azure and in the early stages of developing an application, so my schema is changing frequently. I started out by creating the root database and executing queries against it like these
CREATE TABLE [dbo].[Clients] (
[ClientId] UNIQUEIDENTIFIER NOT NULL primary key clustered default newid(),
[ClientName] NVARCHAR (MAX) NULL
);
go
create federation ClientFederation(cid uniqueidentifier range)
go
use federation ClientFederation(cid='00000000-0000-0000-0000-000000000000') WITH RESET, FILTERING=OFF
go
CREATE TABLE [dbo].[Stuff] (
[StuffId] uniqueidentifier not null default newid(),
[ClientId] UNIQUEIDENTIFIER NOT NULL default federation_filtering_value('cid'),
[StuffName] NVARCHAR (50) NOT NULL,
-- bunch (20+) of other fields
primary key clustered (StuffId, ClientId ASC)
) FEDERATED ON (cid=ClientId);
And that worked out pretty well for the most part. Stuff
is just one table among many similar tables in the federation (and not the real name either)
Well, then like I said, my schema is changing quite frequently, so to change the schema, I'm connecting to the federation member in VS2012 and right-clicking on the table and choosing "View Code" which renders something like this:
CREATE TABLE [dbo].[Stuff] (
[StuffId] uniqueidentifier not null default newid(),
[ClientId] UNIQUEIDENTIFIER NOT NULL default federation_filtering_value('cid'),
[StuffName] NVARCHAR (50) NOT NULL,
-- bunch (20+) of other fields
primary key clustered (StuffId, ClientId ASC)
)
Note, the only thing different is that after the close parentheses, it no longer says FEDERATED ON (cid=ClientId);
. I assumed this was because I'm already connected to a specific federation member so it already knew that information. The weird part is when I tried to run some .net code against it. I'd execute the following code from my app:
cn.Execute(string.Format("USE FEDERATION {0}({1}='{2}') WITH RESET, FILTERING={3}", federationName, distributionName, key, filtered ? "ON" : "OFF"));
and then using dapper:
cn.Query("INSERT Stuff(StuffId, StuffName) VALUES (@StuffId, @stuffName); SELECT * FROM Stuff WHERE StuffId=@stuffId", p); // p has the parameters
but then I'd get the following error message:
DML statements are not supported on non-federated tables in a filtered connection.
Wut? My table is federated, remember? Also, similar code worked wonderfully with other tables. The strange thing about Stuff
is that its schema changed A LOT recently, so it seems to me like maybe me connecting to the federation member directly in VS2012 and making changes there somehow made it not a federated table anymore (there are 3 types of tables in a federated database: http://convective.wordpress.com/2012/03/05/introduction-to-sql-azure-federations/).
So, since I'm early in development, there really isn't anything important in Stuff
so I went ahead and copied its CREATE TABLE code and dropped it completely it from that member, went back to the root database and re-executed the code listed above at the top with the FEDERATED ON (ClientId=cid)
statement again and then re-ran the insert statement from my app and it worked wonderfully!!
So, clearly something happened to make my table not be "federated" anymore. In the end my questions are pretty simple:
1 you can look at sys.federated_table_columns
to tell which tables are federated in members.
2 my guess is you are losing the property because VS is recreating the tables without the federated on clause. unfortunately, vs is not integrated fully into SQLazure so yo need to watch out for these scenarios. otherwise, there is no reason to lose or change the federated on property of a table. you can change all other properties on a federated table like evolve your schema etc. but you either create the table federated and it stays that way or you create it as a reference table and it stays that way.
Hope this helps