So say I have the following tables in my SQL Server 2012 DB:
Person
PersonId
FirstName
LastName
Photo
PhotoId
PersonId (fk)
DateTaken
PhotoFileTable
(all the FileTable columns)
And the photos stored on disk are structured like this:
\\myserver\filestreamshare\People\PersonId\Photo1.tif
And very important: There are a TON of photos ALREADY on disk that need to be added to the database- that's why I thought a FileTable would be cool as it automatically picks them up.
So I need to do 2 things- first, relate the Photo table to the PhotoFileTable so that I can get all photos for a person. And second (and more painful) I want to use Entity Framework 5.0 to do this.
Using the edmx designer, I can't add a table that contains a hierarchyid. Since that is the primary key it seems it should be used as a 1:1 mapping between PhotoId and path_locator (the FileTable hierarchyid). But then I can't add the Photo table either.
What's the best approach here? At the end of the day, I want to have EF objects in C# to use. It ideally would look something like:
class Person
List<Photo>
class Photo
Filestream (to lazy load the image from the filesystem to bitmapimage)
Path (?)
or maybe
class Photo
BitmapImage (lazy load)
Am I going about this the wrong way? Can I get there from here? Thought or suggestions?
Maybe you can try this.
Table:
PhotoTable(
PhotoID uniqueidentifier ROWGUIDCOL NOT NULL,
PhotoImage varbinary(max) FILESTREAM NULL,
)
Insert:
create procedure spPhotoInsert
@PhotoID uniqueidentifier
,@sPhotoPath nvarchar(max)
,@PhotoImage varbinary(max)
as
begin
select
cast('' as varbinary(max)) PhotoImage
into
#ret1
truncate table #ret1
declare @strSql nvarchar(max) = 'select * from OPENROWSET(BULK '''
+ @sPhotoPath + ''',SINGLE_BLOB) AS PhotoImage'
insert into #ret1 EXEC(@strSql)
insert into
PhotoTable
(
PhotoID
,PhotoImage
)
select
@PhotoID
,PhotoImage
from
#ret1
drop table #ret1
end
Update:
create procedure spPhotoUpdate
@PhotoID uniqueidentifier
,@sPhotoPath nvarchar(max)
,@PhotoImage varbinary(max)
as
begin
select
cast('' as varbinary(max)) PhotoImage
into
#ret1
truncate table #ret1
declare @strSql nvarchar(max) = 'select * from OPENROWSET(BULK '''
+ @sPhotoPath + ''',SINGLE_BLOB) AS PhotoImage'
insert into #ret1 EXEC(@strSql)
update
PhotoTable
set
PhotoImage = r.PhotoImage
from
PhotoTable, #ret1 r
where
PhotoID = @PhotoID
drop table #ret1
end
Delete:
create procedure PhotoDelete
@PhotoID uniqueidentifier
as
begin
delete
PhotoTable
where
PhotoID = @PhotoID
end
And the view:
CREATE VIEW vPhotoTable
AS
select
PhotoID
,'' as sPhotoPath
,PhotoImage
from
PhotoTable
After this, the images can be read / write with EF as follows:
//InsertPhoto(sPath)
Entities db = new Entities();
vPhoto p = db.vPhotos.CreateObject();
p.PhotoID = Guid.NewGuid();
p.sPhotoPath = sPath;
db.vPhotos.AddObject(p);
db.SaveChanges();
//UpdatePhoto(PhotoID,sPath):
Entities db = new Entities();
vPhoto p = db.vPhotos.Where(x => x.PhotoID == PhotoID).Single();
p.sPhotoPath = sPath;
db.ObjectStateManager.ChangeObjectState(p, EntityState.Modified);
db.SaveChanges();
//DeletePhoto(PhotoID):
Entities db = new Entities();
vPhoto p = db.vPhotos.Where(x => x.PhotoID == PhotoID).Single();
db.vPhotos.DeleteObject(p);
db.SaveChanges();