Entity Framework 5.0 and FileTable

2019-05-26 17:08发布

问题:

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?

回答1:

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();